package cc.rengu.igas.momp.core.service.trans;

import cc.rengu.igas.momp.common.constant.CommonConstant;
import cc.rengu.igas.momp.common.dao.*;
import cc.rengu.igas.momp.common.dao.impl.*;
import cc.rengu.igas.momp.common.entity.*;
import cc.rengu.igas.momp.common.enums.*;
import cc.rengu.igas.momp.common.model.bean.JsonMfdMcOrderRemark;
import cc.rengu.igas.momp.common.util.JsonOperation;
import cc.rengu.igas.momp.common.util.MompDateUtil;
import cc.rengu.igas.momp.facade.bean.PaymentReturnOrderInfoBean;
import cc.rengu.igas.momp.facade.request.ComboPaymentRefundRequest;
import cc.rengu.igas.momp.facade.response.ComboPaymentRefundResponse;
import cc.rengu.oltp.service.base.RadpService;
import cc.rengu.oltp.service.common.constant.AppConfigConstant;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.common.enums.TransStatusEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.utility.util.*;
import cc.rengu.utility.base.StringUtil;
import cc.rengu.utility.dbs.Database;
import com.alibaba.fastjson.JSONObject;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * (合并)支付退货
 * 减免\卡券\商户手续费优惠计算
 *
 * @author Jinan Liu
 * @since 2020/4/2 17:48
 */
public class ComboPaymentRefundService extends RadpService {

    private String globalInstId;
    /**
     * 渠道交易日期
     */
    private String globalTxnDate;
    /**
     * 渠道交易时间
     */
    private String globalTransTime;
    /**
     * 当前交易系统时间戳
     */
    private String globalTimeStamp;
    /**
     * 退货标志
     */
    private String refundType;

    private String globalTraceNo;
    private String globalOrderId;
    private String globalUserId;
    /**
     * 订单明细表
     */
    private List<TMTxnOrderDet> globalTMTxnOrderDetList;

    /**
     * 原交易日期
     */
    private String origTxnDate;
    /**
     * 原交易流水号
     */
    private String origTraceNo;
    /**
     * 原试算交易日期
     */
    private String origTrialTxnDate;
    /**
     * 原试算交易流水号
     */
    private String origTrialTraceNo;
    //是否是最后一笔退货
    private Boolean isLastDeal = false;
    private BigDecimal zero = BigDecimal.ZERO;

    @Override
    protected int bizInit(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizProcess(String s, int i) {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();

        try {

            ComboPaymentRefundRequest comboPaymentRefundRequest = new ComboPaymentRefundRequest();
            ConvertUtil.convertOutput(comboPaymentRefundRequest);

            /* 检查请求报文并赋值全局变量 */
            messageValidation(comboPaymentRefundRequest);
            // 检查上传字段 不能为负数
            checkTmTxnOrderDetFieldHasNegativeNumber(comboPaymentRefundRequest);

            ComboPaymentRefundResponse comboPaymentRefundResponse = new ComboPaymentRefundResponse();
            comboPaymentRefundResponse.setHeader(comboPaymentRefundRequest.getHeader());
            BizResponse<ComboPaymentRefundResponse> bizResponse = new BizResponse<>();
            bizResponse.setResult(comboPaymentRefundResponse);

            // 服务调用
            BizResponse<ComboPaymentRefundResponse> bizResponseNew = comboPaymentRefund(xmlTreeUtil, comboPaymentRefundRequest, comboPaymentRefundResponse);

            ConvertUtil.convertInput(bizResponseNew.getResult());

        } catch (BizException e) {
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, e.getCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, e.getMessage());
                xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, e.getMessage());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e1));
            }
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespDesc());
                xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, e.getMessage());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e1));
            }
        }

        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizTerminate(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 合并支付退货
     *
     * @param xmlTreeUtil                内部XML树
     * @param comboPaymentRefundRequest  (合并)支付退货接口请求对象
     * @param comboPaymentRefundResponse (合并)支付退货接口应答对象
     * @return cc.rengu.oltp.service.model.BizResponse<cc.rengu.igas.momp.facade.response.ComboPaymentRefundResponse> (合并)支付退货接口应答对象
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/6/11 01:25
     */
    private BizResponse<ComboPaymentRefundResponse> comboPaymentRefund(XmlTreeUtil xmlTreeUtil, ComboPaymentRefundRequest comboPaymentRefundRequest, ComboPaymentRefundResponse comboPaymentRefundResponse) throws Exception {

        BizResponse<ComboPaymentRefundResponse> bizResponse = new BizResponse<>();

        rglog.debug("原交易 ORIGINAL_TXN_DATE=<{}>, ORIGINAL_TRACE_NO=<{}>", origTxnDate, origTraceNo);

        BigDecimal orderAmt = new BigDecimal(comboPaymentRefundRequest.getTransAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        BigDecimal returnAmt = new BigDecimal(comboPaymentRefundRequest.getReturnAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        if (CommonConstant.ZERO == orderAmt.compareTo(returnAmt)) {
            refundType = CommonConstant.REFUND_TYPE_ALL;
            rglog.debug("本次订单流水<{}> 原订单总金额<{}> 本次退款总金额<{}> 全额退货", globalTraceNo, orderAmt, returnAmt);
        } else {
            rglog.debug("本次订单流水<{}> 原订单总金额<{}> 本次退款总金额<{}> 部分退货", globalTraceNo, orderAmt, returnAmt);
            refundType = CommonConstant.REFUND_TYPE_PARTIALLY;
        }

        /* 查询原交易订单流水信息 */
        rglog.info("本次订单流水<{}>对应的原交易订单流水-->交易日期<{}> 交易流水<{}>", globalTraceNo, origTxnDate, origTraceNo);
        TMTxnOrder tmTxnOrder = getOriginalTransactionOrderInfo(globalInstId, origTxnDate, origTraceNo);
        if (null == tmTxnOrder) {
            rglog.error("查询法人机构<{}>在<{}>的原交易订单流水信息<{}>失败!", globalInstId, origTxnDate, origTraceNo);
            throw new BizException(RespCodeEnum.GET_ORI_TRACE_FAILED.getRespCode(), RespCodeEnum.GET_ORI_TRACE_FAILED.getRespDesc());
        }

        /* 根据原交易订单流水表中BIZ_STATUS判断是否可以退货 */
        String bizStatus = tmTxnOrder.getBizStatus();
        if (!BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode().equals(bizStatus) &&
                !(BizStatusEnum.PROCESS_PARTIALLY_REFUNDED.getBizStatusCode().equals(bizStatus))) {
            /* 原交易非支付成功或部分退货状态,不可退货! */
            rglog.error("法人机构<{}> 交易日期<{}> 交易流水<{}>非支付成功或部分退货状态,不可退货!", globalInstId, tmTxnOrder.getTxnDate(), tmTxnOrder.getFrontSeqNum());
            throw new BizException(RespCodeEnum.ORI_STATUS_ERROR_REFUND_FAILED.getRespCode(), RespCodeEnum.ORI_STATUS_ERROR_REFUND_FAILED.getRespDesc());
        }

        /* 开启数据库事务 */
        String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppConfigConstant.DATABASE_CONF_NODE, AppConfigConstant.MOMP_POOL_NAME);
        String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
        if (null != corporation && !corporation.isEmpty()) {
            String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
            dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppConfigConstant.MOMP_POOL_NAME);
        }
        DbsUtil dbsUtil = new DbsUtil(dbPoolName);
        dbsUtil.dbsBeginTransaction();

        //订单预留信息
        String orderRemark = tmTxnOrder.getOrderRemark();
        rglog.info("原交易订单流水<{}> 订单预留信息：<{}>", origTraceNo, orderRemark);
        //原交易虽然成功，但是没有营销时
        if (CommonConstant.DISCOUNT_FLAG_FALSE_CHECK_FLAG_FALSE.equals(orderRemark)) {
            // 插入一条没有营销的新订单流水
            insertSingleRecordIntoTMTxnOrderFalse(dbsUtil, comboPaymentRefundRequest, tmTxnOrder);
            //更新原订单流水
            updateOrigTxnOrderInfoFalse(dbsUtil, tmTxnOrder);

            comboPaymentRefundResponse.setTransAmt(comboPaymentRefundRequest.getTransAmt());
            comboPaymentRefundResponse.setTxnAmt(comboPaymentRefundRequest.getReturnAmt());
            comboPaymentRefundResponse.setReturnAmt(CommonConstant.ZERO_AMOUNT);
            comboPaymentRefundResponse.setBankSubsidy(CommonConstant.ZERO_AMOUNT);
            comboPaymentRefundResponse.setMchntSubsidy(CommonConstant.ZERO_AMOUNT);

            dbsUtil.dbsEndTransaction(true);
        } else {

            /* 查询原交易订单明细信息 */
            List<TMTxnOrderDet> tmTxnOrderDetList = getOriginalTransactionOrderDetailInfo(globalInstId, origTxnDate, origTraceNo);
            if (null == tmTxnOrderDetList || tmTxnOrderDetList.isEmpty()) {
                rglog.error("机构<{}>在<{}>的原交易订单明细信息<{}>失败!", globalInstId, origTxnDate, origTraceNo);
                dbsUtil.dbsEndTransaction(false);
                throw new BizException(RespCodeEnum.FAILED_TO_CHECK_ORIGINAL_TXNDET_INFO_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_CHECK_ORIGINAL_TXNDET_INFO_ERROR.getRespDesc());
            }

            try {
                /* 处理对客类退货部分 */
                rglog.info("机构<{}> 交易流水<{}> 原交易流水<{}> 开始对客类退货部分处理...", globalInstId, globalTraceNo, origTraceNo);
                processToClientRefundProcedure(dbsUtil, comboPaymentRefundRequest, tmTxnOrder, tmTxnOrderDetList);

                /* 处理商户手续费类退货部分 */
                rglog.info("机构<{}> 交易流水<{}> 原交易流水<{}> 开始手续费优惠退货部分处理...", globalInstId, globalTraceNo, origTraceNo);
                processMchntFeeDiscountRefundProcedure(dbsUtil, comboPaymentRefundRequest, tmTxnOrder, tmTxnOrderDetList);

                /* 登记订单明细 */
                if (!globalTMTxnOrderDetList.isEmpty()) {
                    rglog.info("机构<{}> 交易流水<{}> 开始登记本次交易的交易明细信息，共<{}>条...", globalInstId, globalTraceNo, globalTMTxnOrderDetList.size());
                    TMTxnOrderDetMapper tmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
                    for (TMTxnOrderDet tmTxnOrderDet : globalTMTxnOrderDetList) {

                        /* 插入数据 */
                        int returnCode = tmTxnOrderDetMapper.insertSingleRecordIntoTMTxnOrderDet(tmTxnOrderDet);
                        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                            /* 更新失败 */
                            rglog.error("登记法人机构<{}>的营销活动<{}>的商户<{}>的订单明细数据失败! RETURN_CODE=<{}>", tmTxnOrderDet.getInstId(), tmTxnOrderDet.getMcNo(), tmTxnOrderDet.getMchntNo(), returnCode);
                            /* 事务处理失败关闭数据库事务 */
//                            dbsUtil.dbsEndTransaction(false);
                            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespCode());
                            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespDesc());
                            throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
                        }
                        rglog.info("插入法人机构<{}>的营销活动<{}>的商户<{}>的订单明细数据成功", tmTxnOrderDet.getInstId(), tmTxnOrderDet.getMcNo(), tmTxnOrderDet.getMchntNo());
                    }
                }

                /* 插入新订单流水 */
                insertSingleRecordIntoTMTxnOrder(dbsUtil, comboPaymentRefundRequest, tmTxnOrder);

                /* 更新原订单流水 */
                updateOrigTxnOrderInfo(dbsUtil, tmTxnOrder);

                dbsUtil.dbsEndTransaction(true);

                if (CommonConstant.REFUND_TYPE_ALL.equals(refundType)) {
                    /* 全额退款,报文内容和原支付交易内容相同 */
                    comboPaymentRefundResponse.setTransAmt(tmTxnOrder.getOrderAmt());
                    comboPaymentRefundResponse.setTxnAmt(tmTxnOrder.getTxnAmt());
                    comboPaymentRefundResponse.setReturnAmt(tmTxnOrder.getSubsidyAmt());
                    comboPaymentRefundResponse.setBankSubsidy(tmTxnOrder.getBankSubsidyAmt());
                    comboPaymentRefundResponse.setMchntSubsidy(tmTxnOrder.getMchntSubsidyAmt());
                } else {
                    /* 部分退款,优惠部分为0,其他和退货金额相同 */
                    comboPaymentRefundResponse.setTransAmt(comboPaymentRefundRequest.getReturnAmt());
                    comboPaymentRefundResponse.setTxnAmt(comboPaymentRefundRequest.getReturnAmt());
                    comboPaymentRefundResponse.setReturnAmt(CommonConstant.ZERO_AMOUNT);
                    comboPaymentRefundResponse.setBankSubsidy(CommonConstant.ZERO_AMOUNT);
                    comboPaymentRefundResponse.setMchntSubsidy(CommonConstant.ZERO_AMOUNT);
                }

            } catch (Exception e) {
                rglog.error("退款失败!所有数据库操作回滚!<{}>", StringUtil.ExceptionToString(e));
                /* 事务处理失败关闭数据库事务 */
                dbsUtil.dbsEndTransaction(false);
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespDesc());
                throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
            }
        }

        bizResponse.setRspSysId(ChannelEnum.MOMP.getChannelType());
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());

        comboPaymentRefundResponse.setReturnOrderDetailList(comboPaymentRefundRequest.getReturnOrderDetailList());

        comboPaymentRefundResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        comboPaymentRefundResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        bizResponse.setResult(comboPaymentRefundResponse);

        return bizResponse;
    }

    /**
     * 查询合并支付元交易订单流水信息
     *
     * @param instId        法人机构号
     * @param origTransDate 原交易日期
     * @param origTraceNo   原交易流水号
     * @return cc.rengu.igas.momp.common.entity.TMTxnOrder
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/26 10:18
     */
    private TMTxnOrder getOriginalTransactionOrderInfo(String instId, String origTransDate, String origTraceNo) throws Exception {

        TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();
        return tmTxnOrderMapper.selectTransactionOrderInfo(instId, origTransDate, origTraceNo);
    }

    /**
     * 查询合并支付原交易订单明细信息
     *
     * @param instId        法人机构号
     * @param origTransDate 原交易日期
     * @param origTraceNo   原交易流水号
     * @return java.util.List<cc.rengu.igas.momp.common.entity.TMTxnOrderDet>
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/26 11:15
     */
    private List<TMTxnOrderDet> getOriginalTransactionOrderDetailInfo(String instId, String origTransDate, String origTraceNo) throws Exception {

        TMTxnOrderDetMapper tmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
        return tmTxnOrderDetMapper.selectOriginalTransactionOrderDetailListInfo(instId, origTransDate, origTraceNo);
    }

    /**
     * 处理对客类营销活动部分
     *
     * @param dbsUtil                   数据库操作工具类
     * @param comboPaymentRefundRequest 请求报文体
     * @param tmTxnOrder                订单流水信息
     * @param tmTxnOrderDetList         订单明细列表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/26 11:35
     */
    private void processToClientRefundProcedure(DbsUtil dbsUtil, ComboPaymentRefundRequest comboPaymentRefundRequest, TMTxnOrder tmTxnOrder, List<TMTxnOrderDet> tmTxnOrderDetList) throws Exception {

        for (PaymentReturnOrderInfoBean paymentReturnOrderInfoBean : comboPaymentRefundRequest.getReturnOrderDetailList()) {
            processSingleToClientRefundProcedure(dbsUtil, tmTxnOrder, paymentReturnOrderInfoBean, tmTxnOrderDetList);
        }
    }

    /**
     * 处理商户手续费优惠
     *
     * @param dbsUtil                   数据库操作工具类
     * @param comboPaymentRefundRequest 请求报文提
     * @param tmTxnOrderDetList         订单明细列表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/26 10:24
     */
    private void processMchntFeeDiscountRefundProcedure(DbsUtil dbsUtil, ComboPaymentRefundRequest comboPaymentRefundRequest, TMTxnOrder tmTxnOrder, List<TMTxnOrderDet> tmTxnOrderDetList) throws Exception {
        //判断是否已经经过试算
        if (!StringUtil.isNullorEmpty(origTrialTraceNo) && !StringUtil.isNullorEmpty(origTrialTxnDate)) {
            /* 查询原试算交易订单流水信息 */
            rglog.info("查询当前流水<{}>，原交易流水<{}>对应的原交易试算订单流水<{}>信息", globalTraceNo, origTraceNo, origTrialTraceNo);
            TMTxnOrder oriTrialTmTxnOrder = getOriginalTransactionOrderInfo(globalInstId, origTrialTxnDate, origTrialTraceNo);
            if (null == oriTrialTmTxnOrder) {
                rglog.error("查询法人机构<{}>在<{}>的原交易回退试算流水信息<{}>失败!", globalInstId, origTrialTxnDate, origTrialTraceNo);
                throw new BizException(RespCodeEnum.GET_ORI_TRACE_FAILED.getRespCode(), RespCodeEnum.GET_ORI_TRACE_FAILED.getRespDesc());
            }
            /* 查询原试算订单明细信息 */
            List<TMTxnOrderDet> oriTrialTmTxnOrderDetList = getOriginalTransactionOrderDetailInfo(globalInstId, origTrialTxnDate, origTrialTraceNo);
            if (null == oriTrialTmTxnOrderDetList || oriTrialTmTxnOrderDetList.isEmpty()) {
                rglog.error("机构<{}>在<{}>的原试算订单明细信息<{}>失败!", globalInstId, origTrialTxnDate, origTrialTraceNo);
                throw new BizException(RespCodeEnum.GET_ORI_TRACE_FAILED.getRespCode(), RespCodeEnum.GET_ORI_TRACE_FAILED.getRespDesc());
            }

            for (PaymentReturnOrderInfoBean paymentReturnOrderInfoBean : comboPaymentRefundRequest.getReturnOrderDetailList()) {
                //对请求上送的订单循环处理每个商户的
                processSingleToMchntRefundProcedureAlreadyTrial(dbsUtil, tmTxnOrder, paymentReturnOrderInfoBean, tmTxnOrderDetList, oriTrialTmTxnOrder, oriTrialTmTxnOrderDetList);
            }
        } else {
            rglog.info("查询当前流水<{}>，原交易流水<{}> 开始进行未经试算的手续费退货流程...", globalTraceNo, origTraceNo);
            //未经过试算的处理流程
            for (PaymentReturnOrderInfoBean paymentReturnOrderInfoBean : comboPaymentRefundRequest.getReturnOrderDetailList()) {

                processSingleToMchntRefundProcedure(dbsUtil, tmTxnOrder, paymentReturnOrderInfoBean, tmTxnOrderDetList);
            }
        }
    }

    /**
     * 处理单个商户的对客类营销活动部分
     *
     * @param dbsUtil                    数据库操作工具类
     * @param tmTxnOrder                 订单流水信息
     * @param paymentReturnOrderInfoBean (合并)支付退货订单信息对象
     * @param tmTxnOrderDetList          订单明细列表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/26 11:01
     */
    private void processSingleToClientRefundProcedure(DbsUtil dbsUtil, TMTxnOrder tmTxnOrder, PaymentReturnOrderInfoBean paymentReturnOrderInfoBean, List<TMTxnOrderDet> tmTxnOrderDetList) throws Exception {

        int returnCode;
        String instId = tmTxnOrder.getInstId();
        String transDate = tmTxnOrder.getTxnDate();
        String mchntNo = paymentReturnOrderInfoBean.getMchntNo();
        String orderId = tmTxnOrder.getOrderId();

        /* 取原交易明细 */
        List<TMTxnOrderDet> tmTxnOrderDetListMO = tmTxnOrderDetList.stream().filter(item -> ((McTypeEnum.MC_TYPE_MO.getMcTypeCode().equals(item.getMcType().substring(0, 1))) && mchntNo.equals(item.getMchntNo()))).collect(Collectors.toList());
        List<TMTxnOrderDet> tmTxnOrderDetListCP = tmTxnOrderDetList.stream().filter(item -> ((McTypeEnum.MC_TYPE_CP.getMcTypeCode().equals(item.getMcType().substring(0, 1))) && mchntNo.equals(item.getMchntNo()))).collect(Collectors.toList());

        if (!tmTxnOrderDetListMO.isEmpty() && !tmTxnOrderDetListCP.isEmpty()) {
            rglog.info("商户<{}> 对应的原交易明细中有卡券类优惠和减免类优惠", mchntNo);
            /* 商户既有卡券类又有减免类 */
            if (CommonConstant.ONE != tmTxnOrderDetListMO.size() || CommonConstant.ONE != tmTxnOrderDetListCP.size()) {
                /* 卡券和减免类营销活动每个合并支付订单应该只有一条记录，有多条说明是异常情况，不可继续处理 */
                rglog.error("卡券类营销活动合并支付订单应该只有一条记录，减免类营销活动合并支付订单应该只有一条记录，目前存在多条！", tmTxnOrder.getInstId(), tmTxnOrder.getTxnDate(), paymentReturnOrderInfoBean.getMchntNo(), RespCodeEnum.MULTI_ORDER_DETAIL_FOR_SINGLE_MCHNT_ERROR.getRespDesc());
                throw new BizException(RespCodeEnum.MULTI_ORDER_DETAIL_FOR_SINGLE_MCHNT_ERROR.getRespCode(), RespCodeEnum.MULTI_ORDER_DETAIL_FOR_SINGLE_MCHNT_ERROR.getRespDesc());
            }

            /* 卡券处理流程 */
            rglog.debug("开始处理商户<{}>卡券类退款流程...", mchntNo);
            for (TMTxnOrderDet tmTxnOrderDet : tmTxnOrderDetListCP) {
                returnCode = processSingleCouponRefundProcedure(dbsUtil, paymentReturnOrderInfoBean, tmTxnOrderDet);
                if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                    rglog.error("机构<{}>在<{}>的订单<{}>中商户<{}>的卡券类退款失败!", instId, transDate, orderId, mchntNo);
                    throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
                }
            }

            /* 满减处理流程 */
            rglog.debug("开始处理商户<{}>减免类退款流程...", mchntNo);
            for (TMTxnOrderDet tmTxnOrderDet : tmTxnOrderDetListMO) {
                returnCode = processSingleMoneyOffRefundProcedure(dbsUtil, paymentReturnOrderInfoBean, tmTxnOrderDet);
                if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                    rglog.error("机构<{}>在<{}>的订单<{}>中商户<{}>的减免类退款失败!", instId, transDate, orderId, mchntNo);
                    throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
                }
            }

        } else if (!tmTxnOrderDetListMO.isEmpty()) {
            /* 商户只有减免类 */
            rglog.info("待处理待退款商户<{}>明细只有减免类,开始处理减免类退款流程...", mchntNo);
            for (TMTxnOrderDet tmTxnOrderDet : tmTxnOrderDetListMO) {
                returnCode = processSingleMoneyOffRefundProcedure(dbsUtil, paymentReturnOrderInfoBean, tmTxnOrderDet);
                if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                    rglog.error("机构<{}>在<{}>的订单<{}>中商户<{}>的减免部分退款失败!", instId, transDate, orderId, mchntNo);
                    throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
                }
            }
        } else if (!tmTxnOrderDetListCP.isEmpty()) {
            /* 商户只有卡券类 */
            rglog.info("待处理待退款商户<{}>明细只有卡券类,开始处理卡券类退款流程...", mchntNo);
            for (TMTxnOrderDet tmTxnOrderDet : tmTxnOrderDetListCP) {
                returnCode = processSingleCouponRefundProcedure(dbsUtil, paymentReturnOrderInfoBean, tmTxnOrderDet);
                if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                    rglog.error("机构<{}>在<{}>的订单<{}>中商户<{}>的卡券部分退款失败!", instId, transDate, orderId, mchntNo);
                    throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
                }
            }

        } else {
            /* 未找到对应商户的对客类营销活动信息，不处理！ */
            rglog.error("机构<{}>在<{}>的商户<{}>未参加任何对客类营销活动，不进行任何计算!", instId, transDate, mchntNo);
        }
    }

    /**
     * 处理单个商户的商户手续费优惠营销活动部分
     *
     * @param dbsUtil                    数据库操作工具类
     * @param tmTxnOrder                 订单流水信息
     * @param paymentReturnOrderInfoBean (合并)支付退货订单信息
     * @param tmTxnOrderDetList          订单明细列表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/26 18:11
     */
    private void processSingleToMchntRefundProcedure(DbsUtil dbsUtil, TMTxnOrder tmTxnOrder, PaymentReturnOrderInfoBean paymentReturnOrderInfoBean, List<TMTxnOrderDet> tmTxnOrderDetList) throws Exception {

        int returnCode;
        String instId = tmTxnOrder.getInstId();
        String transDate = tmTxnOrder.getTxnDate();
        String mchntNo = paymentReturnOrderInfoBean.getMchntNo();
        String orderId = tmTxnOrder.getOrderId();

        /* 取原交易明细 */
        List<TMTxnOrderDet> tmTxnOrderDetListMdf = tmTxnOrderDetList.stream().filter(item -> ((McTypeEnum.MC_TYPE_MFD.getMcTypeCode().equals(item.getMcType().substring(0, 1))) && mchntNo.equals(item.getMchntNo()))).collect(Collectors.toList());
        if (tmTxnOrderDetListMdf.isEmpty()) {
            rglog.error("法人机构<{}>在<{}>的商户订单号<{}>下的商户<{}>的子订单的待处理商户手续费优惠回退数据为0条,继续处理下一条订单明细数据!", instId, transDate, orderId, mchntNo);
            return;
        }

        /* 如果超过1条数据,则返回失败 */
        if (CommonConstant.ONE != tmTxnOrderDetListMdf.size()) {
            rglog.error("法人机构<{}>在<{}>的商户订单号<{}>下的商户<{}>的子订单的待处理商户手续费优惠回退数据多于1条,返回失败,不做处理!", instId, transDate, orderId, mchntNo);
            throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
        }

        /* 商户手续费优惠处理流程 */
        returnCode = processSingleMchntFeeDiscountRefundProcedure(dbsUtil, paymentReturnOrderInfoBean, tmTxnOrder, tmTxnOrderDetListMdf.get(CommonConstant.ZERO));
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("机构<{}>在<{}>的订单<{}>中商户<{}>的卡券部分退款失败!", instId, transDate, orderId, mchntNo);
            throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
        }
    }

    /**
     * 单个卡券明细退货
     *
     * @param dbsUtil                    数据库操作工具类
     * @param paymentReturnOrderInfoBean (合并)支付退货订单信息对象
     * @param tmTxnOrderDet              订单明细信息
     * @return int
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/26 17:06
     */
    private int processSingleCouponRefundProcedure(DbsUtil dbsUtil, PaymentReturnOrderInfoBean paymentReturnOrderInfoBean, TMTxnOrderDet tmTxnOrderDet) throws Exception {

        /* 判断是否已退货 */
        if (!BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode().equals(tmTxnOrderDet.getBizStatus())) {
            rglog.error("订单明细的业务状态异常，不可退款！");
            return CommonConstant.PROCESS_FAILED;
        }

        rglog.info("开始处理商户<{}> 对客类营销活动统计值...", tmTxnOrderDet.getMchntNo());
        /* 扣减对客类营销活动统计值 */
        reverseToClientMcStatistics(dbsUtil, tmTxnOrderDet);

        rglog.info("开始处理商户<{}> 对应的用户所用卡券信息...", tmTxnOrderDet.getMchntNo());
        /* 更新卡券状态 */
        reverseCouponInfo(dbsUtil, tmTxnOrderDet);

        /* 退订单明细 */
        tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode());
        tmTxnOrderDet.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmTxnOrderDet.setUpdateTime(globalTimeStamp);
        reverseTxnOrderDetail(dbsUtil, tmTxnOrderDet);

        /* 转换订单明细 */
        TMTxnOrderDet tmTxnOrderDet1 = convertTxnOrderDetail(paymentReturnOrderInfoBean, tmTxnOrderDet);
        if (null == tmTxnOrderDet1) {
            rglog.error("订单流水<{}> 商户<{}>转换订单明细失败!", globalTraceNo, tmTxnOrderDet.getMchntNo());
//            dbsUtil.dbsEndTransaction(false);
            throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
        }
        globalTMTxnOrderDetList.add(tmTxnOrderDet1);

        /* 应答报文拼接 */
        paymentReturnOrderInfoBean.setCouponMcNo(tmTxnOrderDet.getMcNo());
        paymentReturnOrderInfoBean.setCouponTotalSubsidy(tmTxnOrderDet.getSubsidy());
        paymentReturnOrderInfoBean.setCouponBankSubsidy(tmTxnOrderDet.getBankSubsidy());
        paymentReturnOrderInfoBean.setCouponMchntSubsidy(tmTxnOrderDet.getMchntSubsidy());

        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 单个减免类订单明细退货
     *
     * @param dbsUtil                    数据库工具类
     * @param paymentReturnOrderInfoBean (合并)支付退货订单信息对象
     * @param tmTxnOrderDet              订单明细信息
     * @return int
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/26 17:06
     */
    private int processSingleMoneyOffRefundProcedure(DbsUtil dbsUtil, PaymentReturnOrderInfoBean paymentReturnOrderInfoBean, TMTxnOrderDet tmTxnOrderDet) throws Exception {

        /* 判断是否已退货 */
        if (!BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode().equals(tmTxnOrderDet.getBizStatus())) {
            /* 对客类营销活动只有全额退款 */
            rglog.error("商户<{}> 订单明细的业务状态异常，不可退款！", tmTxnOrderDet.getMchntNo());
            return CommonConstant.PROCESS_FAILED;
        }

        /* 扣减对客类营销活动统计值 */
        reverseToClientMcStatistics(dbsUtil, tmTxnOrderDet);

        /* 退订单明细 */
        tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode());
        tmTxnOrderDet.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmTxnOrderDet.setUpdateTime(globalTimeStamp);
        reverseTxnOrderDetail(dbsUtil, tmTxnOrderDet);

        /* 转换订单明细 */
        TMTxnOrderDet tmTxnOrderDet1 = convertTxnOrderDetail(paymentReturnOrderInfoBean, tmTxnOrderDet);
        if (null == tmTxnOrderDet1) {
            rglog.error("订单流水<{}> 商户<{}> 转换订单明细失败!", globalTraceNo, tmTxnOrderDet.getMchntNo());
            throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
        }
        globalTMTxnOrderDetList.add(tmTxnOrderDet1);

        paymentReturnOrderInfoBean.setMoneyOffMcNo(tmTxnOrderDet.getMcNo());
        BigDecimal txnAmt = new BigDecimal(tmTxnOrderDet.getOriginalAmt()).subtract(new BigDecimal(tmTxnOrderDet.getSubsidy())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        paymentReturnOrderInfoBean.setMoneyOffTxnAmt(txnAmt.toString());
        paymentReturnOrderInfoBean.setMoneyOffSubsidyTotal(tmTxnOrderDet.getSubsidy());
        paymentReturnOrderInfoBean.setMoneyOffSubsidyBank(tmTxnOrderDet.getBankSubsidy());
        paymentReturnOrderInfoBean.setMoneyOffSubsidyMchnt(tmTxnOrderDet.getMchntSubsidy());

        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 单个商户手续费优惠类订单明细退货
     *
     * @param dbsUtil                    数据库操作工具类
     * @param paymentReturnOrderInfoBean (合并)支付退货订单信息
     * @param tmTxnOrder                 原交易订单流水信息
     * @param tmTxnOrderDet              原交易订单明细信息
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/26 19:17
     */
    private int processSingleMchntFeeDiscountRefundProcedure(DbsUtil dbsUtil, PaymentReturnOrderInfoBean paymentReturnOrderInfoBean, TMTxnOrder tmTxnOrder, TMTxnOrderDet tmTxnOrderDet) throws Exception {

        int limitFlag;
        //原交易对应的规则编号
        String ruleIndex = tmTxnOrderDet.getRuleIndex();
        String mchntNo = tmTxnOrderDet.getMchntNo();

        /* 判断是全量退货还是部分退货 */
        BigDecimal origFeeReceivableAmt = new BigDecimal(tmTxnOrderDet.getOriginalAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        BigDecimal refundFeeReceivableAmt = new BigDecimal(paymentReturnOrderInfoBean.getMchntFeeReceivable()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        if (refundFeeReceivableAmt.compareTo(origFeeReceivableAmt) > CommonConstant.ZERO) {
            rglog.error("本笔退货交易应收手续费金额<{}> 大于原交易应收手续费金额<{}>  异常！", refundFeeReceivableAmt, origFeeReceivableAmt);
            dbsUtil.dbsEndTransaction(false);
            throw new BizException(RespCodeEnum.FAILED_TO_REFUND_TRIAL_EXCEED.getRespCode(), RespCodeEnum.FAILED_TO_REFUND_TRIAL_EXCEED.getRespDesc());
        }

        rglog.info("交易流水<{}> 交易日期<{}> 商户<{}> 手续费优惠规则<{}>", origTraceNo, origTxnDate, mchntNo, ruleIndex);

        MchntInfoMapper mchntInfoMapper = new MchntInfoMapperImpl();
        TBMchntBaseInfo mchntBaseInfo = mchntInfoMapper.selectMompMchntBaseInfoByPrimaryKey(tmTxnOrder.getInstId(), mchntNo);
        if (null == mchntBaseInfo) {
            //查询不到商户信息，流程结束
            rglog.error("查询商户基本信息信息失败, INST_ID=<{}>, MCHNT_NO=<{}>", tmTxnOrder.getInstId(), mchntNo);
            throw new BizException(RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespDesc());
        }
        //商户性质
        String mchntType = mchntBaseInfo.getMchntType();
        //独立营销活动标识
        String idpdCmavyFlg = mchntBaseInfo.getMarketFlag();
        //连锁商户号
        String chainMchntNo = mchntBaseInfo.getChainMchntNo();
        //是否独立维护商户资料
        String independentDataFlag = mchntBaseInfo.getIndependentDataFlag();
        if (CommonConstant.YES.equals(independentDataFlag) && MchntTypeEnum.CHAIN_MCHNT_STORE.getMchntType().equals(mchntType) && CommonConstant.ZERO_COMMON_CONSTANT.equals(idpdCmavyFlg)) {
            rglog.info("商户<{}> 商户类型为11:连锁商户门店，是否独立维护商户资料<{}> 商户独立营销活动标识为<{}>,原正向交易计算营销时根据上级商户<{}> 获取营销活动计算的!", mchntNo, independentDataFlag, idpdCmavyFlg, chainMchntNo);
            mchntNo = chainMchntNo;
        } else {
            rglog.info("商户<{}> 是否独立维护商户资料<{}> 商户类型为<{}> 原正向交易无需判断独立营销活动标识，均使用当前商户号计算的营销！", mchntBaseInfo.getMchntNo(), independentDataFlag, mchntType);
        }

        TMStatMfdCriteriaMapper tmStatMfdCriteriaMapper = new TMStatMfdCriteriaMapperImpl();
        TMStatMfdCriteria tmStatMfdCriteria = tmStatMfdCriteriaMapper.selectTMStatMfdCriteriaByUsingMchntNoAndDateRange(tmTxnOrderDet.getInstId(), mchntNo, tmTxnOrderDet.getTxnDate());
        if (null == tmStatMfdCriteria) {
            /* 未取到数据,说明当前退货日期已超过原支付交易商户统计周期,不回退额度 */
            rglog.info("当前退货交易日期<{}> 未取到原支付交易在<{}>的流水号<{}>订单号<{}>的达标统计表数据,不回退统计周期数据!", globalTxnDate, tmTxnOrderDet.getTxnDate(), tmTxnOrderDet.getFrontSeqNum(), tmTxnOrderDet.getOrderId());
            limitFlag = CommonConstant.FLAG_NOT_SET;
        } else {
            /* 判断当前退货交易日期是否在原支付交易商户统计周期内 */
            if (CommonConstant.ZERO == MompDateUtil.checkDateRange(globalTxnDate, tmStatMfdCriteria.getPeriodStartDate(), tmStatMfdCriteria.getPeriodEndDate())) {
                rglog.info("当前退货交易日期<{}>未超出原支付交易在<{}>的流水号<{}>订单号<{}>的统计周期,继续判断退货时是否到达优惠额度限制!", globalTxnDate, tmTxnOrderDet.getTxnDate(), tmTxnOrderDet.getFrontSeqNum(), tmTxnOrderDet.getOrderId());
                McMchntFeeDiscountTransData mcMchntFeeDiscountTransData = new McMchntFeeDiscountTransData();

                Boolean isReachRuleOrMchntLimit;
                //交易规则为0，则为新商户免手续费的，具体规则号的则为存量商户的
                if (CommonConstant.ZERO_COMMON_CONSTANT.equals(ruleIndex)) {
                    //获取新商户当前各维度统计数据值
                    fetchNewMchntFeeDiscountMcQuotaData(mcMchntFeeDiscountTransData, tmStatMfdCriteria);
                    //判断各维度是否达到上限
                    isReachRuleOrMchntLimit = judgeNewMchntIsReachLimit(mcMchntFeeDiscountTransData, tmStatMfdCriteria);
                } else {
                    //获取当前各维度统计数据值
                    fetchAllMchntFeeDiscountMcQuotaData(mcMchntFeeDiscountTransData, tmStatMfdCriteria);
                    //判断各维度是否达到上限
                    isReachRuleOrMchntLimit = judgeIsReachRuleOrMchntLimit(mcMchntFeeDiscountTransData, tmStatMfdCriteria);
                }

                if (isReachRuleOrMchntLimit) {
                    rglog.info("累计交易额度未达到上限值,需要回退统计周期数据!");
                    limitFlag = CommonConstant.FLAG_SET;
                } else {
                    rglog.info("累计交易额度已达到上限值,不需要回退统计周期数据!");
                    limitFlag = CommonConstant.FLAG_NOT_SET;
                }
            } else {
                rglog.info("当前退货交易日期<{}>已超出原支付交易在<{}>的流水号<{}>订单号<{}>的统计周期,不回退统计周期数据!", globalTxnDate, tmTxnOrder.getTxnDate(), tmTxnOrder.getFrontSeqNum(), tmTxnOrder.getOrderId());
                limitFlag = CommonConstant.FLAG_NOT_SET;
            }
        }

        if (CommonConstant.IS_EQUAL_TO == origFeeReceivableAmt.compareTo(refundFeeReceivableAmt)) {
            rglog.info("当前退货交易日期<{}> 原交易应收手续费<{}> 退货交易应退手续费<{}> 本次为全额退货!", globalTxnDate, origFeeReceivableAmt, refundFeeReceivableAmt);
            /* 全额退货场景 */
            if (CommonConstant.FLAG_NOT_SET == limitFlag) {
                /* 无需回退额度 */
                rglog.info("不回退统计周期数据，流程继续!", globalTxnDate, tmTxnOrder.getTxnDate(), tmTxnOrder.getFrontSeqNum(), tmTxnOrder.getOrderId());
            } else {
                rglog.info("需要回退额度，进行回退额度处理...", globalTxnDate, tmTxnOrder.getTxnDate(), tmTxnOrder.getFrontSeqNum(), tmTxnOrder.getOrderId());
                /* 需回退额度 */
                reverseFullyMchntFeeDiscountMcStatistics(dbsUtil, tmTxnOrderDet, mchntNo);
            }

            paymentReturnOrderInfoBean.setMchntFeeDiscount(tmTxnOrderDet.getSubsidy());
            BigDecimal mchntFeeActual = new BigDecimal(tmTxnOrderDet.getOriginalAmt()).subtract(new BigDecimal(tmTxnOrderDet.getSubsidy())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            paymentReturnOrderInfoBean.setMchntFeeActual(mchntFeeActual.toString());
            //全额退款，所以本笔退货肯定是最后一笔退货
            isLastDeal = true;

            //登记退货统计表数据
            recordTMStatRefundFullyNoTrail(tmTxnOrder, tmTxnOrderDet, paymentReturnOrderInfoBean);

        } else {
            /* 计算本次退款金额 */
            calculatePartiallyRefundFeeAmt(dbsUtil, paymentReturnOrderInfoBean, tmTxnOrder, tmTxnOrderDet);

            /* 部分退货场景 */
            if (CommonConstant.FLAG_NOT_SET == limitFlag) {
                /* 无需回退额度 */
                rglog.info("当前退货交易日期<{}>已超出原支付交易在<{}>的流水号<{}>订单号<{}>的统计周期,不回退统计周期数据!", globalTxnDate, tmTxnOrder.getTxnDate(), tmTxnOrder.getFrontSeqNum(), tmTxnOrder.getOrderId());

            } else {
                /* 需回退额度 */
                reversePartiallyMchntFeeDiscountMcStatistics(dbsUtil, paymentReturnOrderInfoBean, tmTxnOrderDet, mchntNo);
            }
        }
        //本笔退货交易时最后一笔退款时，原订单明细更新为全额退货，否则为部分退货
        if (isLastDeal) {
            tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode());
        } else {
            tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_PARTIALLY_REFUNDED.getBizStatusCode());
        }

        /* 生成本次退款的的订单明细数据 */
        TMTxnOrderDet tmTxnOrderDet1 = convertTxnOrderDetail(paymentReturnOrderInfoBean, tmTxnOrderDet);
        if (null == tmTxnOrderDet1) {
            rglog.error("订单流水<{}> 商户<{}>转换订单明细失败!", globalTraceNo, tmTxnOrderDet.getMchntNo());
            dbsUtil.dbsEndTransaction(false);
            throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
        }
        //如果手续费回退的交易有手续费优惠值，则登记订单明细表，如果没有则不登记
        if (new BigDecimal(paymentReturnOrderInfoBean.getMchntFeeDiscount()).compareTo(BigDecimal.ZERO) != CommonConstant.ZERO
                || CommonConstant.ONE_COMMON_CONSTANT.equals(tmTxnOrderDet1.getRemark1())) {
            globalTMTxnOrderDetList.add(tmTxnOrderDet1);
        }

        rglog.info("开始更新法人机构<> 日期<{}> 流水号<{}> 原交易订单明细...", tmTxnOrderDet.getInstId(), tmTxnOrderDet.getTxnDate(), tmTxnOrderDet.getFrontSeqNum());
        /* 退订单明细 */
        tmTxnOrderDet.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmTxnOrderDet.setUpdateTime(globalTimeStamp);
        reverseTxnOrderDetail(dbsUtil, tmTxnOrderDet);

        paymentReturnOrderInfoBean.setMchntFeeDiscountMcNo(tmTxnOrderDet.getMcNo());

        return CommonConstant.PROCESS_SUCCESS;
    }


    /**
     * 处理对客类营销活动统计数据
     *
     * @param dbsUtil       数据库操作工具类
     * @param tmTxnOrderDet 订单明细信息
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/26 17:43
     */
    private void reverseToClientMcStatistics(DbsUtil dbsUtil, TMTxnOrderDet tmTxnOrderDet) throws Exception {

        BigDecimal zero = BigDecimal.ZERO.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        BigDecimal oriMchntSubsidy = new BigDecimal(tmTxnOrderDet.getMchntSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        BigDecimal oriBankSubsidy = new BigDecimal(tmTxnOrderDet.getBankSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        /* 更新对客户营销活动单日统计表表数据 */
        TMStat2CDay tmStat2CDay = new TMStat2CDay();

        tmStat2CDay.setInstId(tmTxnOrderDet.getInstId());
        tmStat2CDay.setMcNo(tmTxnOrderDet.getMcNo());
        tmStat2CDay.setTxnDate(tmTxnOrderDet.getTxnDate());
        tmStat2CDay.setRuleIndex(tmTxnOrderDet.getRuleIndex());
        tmStat2CDay.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStat2CDay.setUpdateTime(globalTimeStamp);

        BigDecimal minusOne = BigDecimal.ZERO.subtract(BigDecimal.ONE).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        String minusOneString = minusOne.toString();
        String totalSubsidy = new BigDecimal(tmTxnOrderDet.getSubsidy()).multiply(minusOne).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
        String bankSubsidy = new BigDecimal(tmTxnOrderDet.getBankSubsidy()).multiply(minusOne).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
        String mchntSubsidy = new BigDecimal(tmTxnOrderDet.getMchntSubsidy()).multiply(minusOne).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
        String txnQtyAcc = new BigDecimal(tmTxnOrderDet.getOriginalAmt()).multiply(minusOne).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();

        tmStat2CDay.setTotalQtyAcc(minusOneString);
        tmStat2CDay.setTotalAmtAcc(totalSubsidy);

        if (BigDecimal.ZERO.compareTo(oriBankSubsidy) == CommonConstant.ZERO) {
            tmStat2CDay.setBankQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        } else {
            tmStat2CDay.setBankQtyAcc(minusOneString);
        }

        tmStat2CDay.setBankAmtAcc(bankSubsidy);
        tmStat2CDay.setTxnQtyAcc(txnQtyAcc);
        if (BigDecimal.ZERO.compareTo(oriMchntSubsidy) == CommonConstant.ZERO) {
            tmStat2CDay.setMchntQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        } else {
            tmStat2CDay.setMchntQtyAcc(minusOneString);
        }

        tmStat2CDay.setMchntAmtAcc(mchntSubsidy);

        tmStat2CDay.setMchntQty(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStat2CDay.setExposureQty(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStat2CDay.setExposurePeopleQty(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStat2CDay.setAvgTotalAmt(CommonConstant.ZERO_AMOUNT);
        tmStat2CDay.setAvgBankAmt(CommonConstant.ZERO_AMOUNT);
        tmStat2CDay.setAvgMchntAmt(CommonConstant.ZERO_AMOUNT);
        tmStat2CDay.setOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStat2CDay.setCreateTime(globalTimeStamp);
        tmStat2CDay.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStat2CDay.setUpdateTime(globalTimeStamp);

        TMStat2CDayMapper tmStat2CDayMapper = new TMStat2CDayMapperImpl();
        int returnCode = tmStat2CDayMapper.updateToClientMcDayStatistics(tmStat2CDay);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            if (Database.DBS_NOT_FOUND == returnCode) {
                int insertReturnCode = tmStat2CDayMapper.insertSingleToClientMcDayStatistics(tmStat2CDay);
                if (CommonConstant.PROCESS_SUCCESS != insertReturnCode) {
                    rglog.error("插入对客户营销活动单日统计表规则为<{}>数据失败!", tmStat2CDay.getRuleIndex());
                    throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
                }
            } else {
                rglog.error("更新对客户营销活动单日统计表数据失败!");
                throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
            }
        }

        //如果当规则不是0 ，则还需要更新规则为0的记录（走到这，规则肯定不为0）
        if (!CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStat2CDay.getRuleIndex())) {
            tmStat2CDay.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);

            returnCode = tmStat2CDayMapper.updateToClientMcDayStatistics(tmStat2CDay);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                if (Database.DBS_NOT_FOUND == returnCode) {
                    int insertReturnCode2 = tmStat2CDayMapper.insertSingleToClientMcDayStatistics(tmStat2CDay);
                    if (CommonConstant.PROCESS_SUCCESS != insertReturnCode2) {
                        /* 插入数据失败 */
                        rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>对客户营销活动单日统计表失败! RETURN_CODE=<{}>", tmStat2CDay.getInstId(), tmStat2CDay.getMcNo(), tmStat2CDay.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                } else {
                    /* 更新数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的对客户营销活动单日统计表数据失败! RETURN_CODE=<{}>", tmStat2CDay.getInstId(), tmStat2CDay.getMcNo(), tmStat2CDay.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            }
        }

        /* 更新对客户营销活动商户单日统计表的数据 */
        TMStat2CMchntDay tmStat2CMchntDay = new TMStat2CMchntDay();
        tmStat2CMchntDay.setInstId(tmTxnOrderDet.getInstId());
        tmStat2CMchntDay.setTxnDate(tmTxnOrderDet.getTxnDate());
        tmStat2CMchntDay.setMcNo(tmTxnOrderDet.getMcNo());
        tmStat2CMchntDay.setMchntNo(tmTxnOrderDet.getMchntNo());
        if (oriMchntSubsidy.compareTo(zero) > CommonConstant.ZERO) {
            tmStat2CMchntDay.setTotalQtyAcc(minusOneString);
        } else {
            tmStat2CMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }
        tmStat2CMchntDay.setTotalAmtAcc(mchntSubsidy);

        tmStat2CMchntDay.setBankAmtAcc(bankSubsidy);
        if (oriBankSubsidy.compareTo(zero) > CommonConstant.ZERO) {
            tmStat2CMchntDay.setBankQtyAcc(minusOneString);
        } else {
            tmStat2CMchntDay.setBankQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }
        tmStat2CMchntDay.setAvgBankAmtAcc(CommonConstant.ZERO_AMOUNT);
        tmStat2CMchntDay.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStat2CMchntDay.setUpdateTime(globalTimeStamp);

        tmStat2CMchntDay.setAvgAmtAcc(CommonConstant.ZERO_AMOUNT);
        tmStat2CMchntDay.setTxnAmtAcc(txnQtyAcc);
        tmStat2CMchntDay.setExposureQty(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStat2CMchntDay.setExposurePeopleQty(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStat2CMchntDay.setOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStat2CMchntDay.setCreateTime(globalTimeStamp);
        tmStat2CMchntDay.setLastOprId(CommonConstant.DEFAULT_OPR_ID);

        TMStat2CMchntDayMapper tmStat2CMchntDayMapper = new TMStat2CMchntDayMapperImpl();
        returnCode = tmStat2CMchntDayMapper.updateToClientMcMchntDayStatistics(tmStat2CMchntDay);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            if (Database.DBS_NOT_FOUND == returnCode) {
                tmStat2CMchntDay.setCreateTime(globalTimeStamp);
                tmStat2CMchntDay.setOprId(CommonConstant.DEFAULT_OPR_ID);
                int insertReturnCode = tmStat2CMchntDayMapper.insertSingleToClientMcMchntDayStatistics(tmStat2CMchntDay);
                if (CommonConstant.PROCESS_SUCCESS != insertReturnCode) {
                    rglog.error("插入对客户营销活动商户单日统计表规则为<{}>数据失败!", tmStat2CDay.getRuleIndex());
                    throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
                }
            } else {
                rglog.error("更新对客户营销活动商户单日统计表数据失败!");
                throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
            }
        }
    }

    /**
     * 回退卡券
     *
     * @param dbsUtil       数据库操作工具类
     * @param tmTxnOrderDet 订单明细信息
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/26 17:46
     */
    private void reverseCouponInfo(DbsUtil dbsUtil, TMTxnOrderDet tmTxnOrderDet) throws Exception {

        /* 更新卡券信息表 */
        TMCouponInfo tmCouponInfo = new TMCouponInfo();
        tmCouponInfo.setInstId(tmTxnOrderDet.getInstId());

        JSONObject relativeDataJson = JSONObject.parseObject(tmTxnOrderDet.getRelativeData());
        //原商户订单明细金额
        String couponNo = relativeDataJson.get("couponNo").toString();
        tmCouponInfo.setCouponNo(couponNo);
        tmCouponInfo.setCouponStatus(CouponStatusEnum.NOT_REDEEMED.getCouponStatusCode());
        tmCouponInfo.setOrderId("");
        tmCouponInfo.setRedeemTime("");

        CouponInfoMapper couponInfoMapper = new CouponInfoMapperImpl();
        int returnCode = couponInfoMapper.reverseRedeemedCoupon(tmCouponInfo);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("回退用户使用的卡券时，更新卡券信息表数据失败!");
//            dbsUtil.dbsEndTransaction(false);
            throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
        }
    }

    /**
     * 处理商户手续费营销活动全额回退统计数据
     *
     * @param dbsUtil       数据库操作工具类
     * @param tmTxnOrderDet 订单明细表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/27 09:51
     */
    private void reverseFullyMchntFeeDiscountMcStatistics(DbsUtil dbsUtil, TMTxnOrderDet tmTxnOrderDet, String mchntNo) throws Exception {

        JsonMfdMcOrderRemark jsonMfdMcOrderRemark = JsonOperation.parseMfdMcOrderDetailOrderRemark(tmTxnOrderDet.getOrderRemark(), rglog);

        /* 更新手续费减免活动单日统计表数据 */
        TMStatMfdDay tmStatMfdDay = new TMStatMfdDay();

        tmStatMfdDay.setInstId(tmTxnOrderDet.getInstId());
        tmStatMfdDay.setMcNo(tmTxnOrderDet.getMcNo());
        tmStatMfdDay.setTxnDate(globalTxnDate);
        tmStatMfdDay.setRuleIndex(tmTxnOrderDet.getRuleIndex());

        BigDecimal minusOne = BigDecimal.ZERO.subtract(BigDecimal.ONE).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        String minusOneString = minusOne.toString();
        String totalSubsidy = new BigDecimal(tmTxnOrderDet.getSubsidy()).multiply(minusOne).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
        String orderAmt = new BigDecimal(jsonMfdMcOrderRemark.getOrderAmt()).multiply(minusOne).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();

        String disTxAmt = tmTxnOrderDet.getDisTxAmt();
        if (null != disTxAmt) {
            orderAmt = new BigDecimal(disTxAmt).multiply(minusOne).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
        }

        tmStatMfdDay.setTotalQtyAcc(minusOneString);
        tmStatMfdDay.setTotalAmtAcc(totalSubsidy);
        tmStatMfdDay.setTxnQtyAcc(minusOneString);
        tmStatMfdDay.setTxnAmtAcc(orderAmt);

        tmStatMfdDay.setMchntQty(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdDay.setMchntOldQualified(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdDay.setMchntNewQualified(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdDay.setMchntExitQty(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdDay.setAvgAmt(CommonConstant.ZERO_AMOUNT);
        tmStatMfdDay.setPaidAmt(CommonConstant.ZERO_AMOUNT);
        tmStatMfdDay.setOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStatMfdDay.setCreateTime(globalTimeStamp);
        tmStatMfdDay.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStatMfdDay.setUpdateTime(globalTimeStamp);

        TMStatMfdDayMapper tmStatMfdDayMapper = new TMStatMfdDayMapperImpl();
        int returnCode = tmStatMfdDayMapper.updateMchntFeeDiscountDayStatistics(tmStatMfdDay);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            if (Database.DBS_NOT_FOUND == returnCode) {
                int returnCode2 = tmStatMfdDayMapper.insertTMStatMfdDay(tmStatMfdDay);
                if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                    /* 插入数据失败 */
                    rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            } else {
                /* 更新数据失败 */
                rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
            }
        }
        //如果当规则不是0 ，则还需要更新规则为0的记录
        if (!CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStatMfdDay.getRuleIndex())) {
            tmStatMfdDay.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);

            returnCode = tmStatMfdDayMapper.updateMchntFeeDiscountDayStatistics(tmStatMfdDay);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                if (Database.DBS_NOT_FOUND == returnCode) {
                    int returnCode2 = tmStatMfdDayMapper.insertTMStatMfdDay(tmStatMfdDay);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                        /* 插入数据失败 */
                        rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                } else {
                    /* 更新数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            }
        }

        /* 更新手续费减免活动商户单日统计表 */
        TMStatMfdMchntDay tmStatMfdMchntDay = new TMStatMfdMchntDay();
        tmStatMfdMchntDay.setInstId(tmTxnOrderDet.getInstId());
        tmStatMfdMchntDay.setMcNo(tmTxnOrderDet.getMcNo());
        tmStatMfdMchntDay.setTxnDate(globalTxnDate);
        tmStatMfdMchntDay.setMchntNo(mchntNo);
        tmStatMfdMchntDay.setRuleIndex(tmTxnOrderDet.getRuleIndex());

        tmStatMfdMchntDay.setTotalQtyAcc(minusOneString);
        tmStatMfdMchntDay.setTotalAmtAcc(totalSubsidy);
        tmStatMfdMchntDay.setTxnQtyAcc(minusOneString);
        tmStatMfdMchntDay.setTxnAmtAcc(orderAmt);

        tmStatMfdMchntDay.setTotalAvgAmt(CommonConstant.ZERO_AMOUNT);
        tmStatMfdMchntDay.setExitStatus(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdMchntDay.setCashbackStatus(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdMchntDay.setCashbackAmt(CommonConstant.ZERO_AMOUNT);
        tmStatMfdMchntDay.setOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStatMfdMchntDay.setCreateTime(globalTimeStamp);
        tmStatMfdMchntDay.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStatMfdMchntDay.setUpdateTime(globalTimeStamp);

        TMStatMfdMchntDayMapper tmStatMfdMchntDayMapper = new TMStatMfdMchntDayMapperImpl();
        returnCode = tmStatMfdMchntDayMapper.updateMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            if (Database.DBS_NOT_FOUND == returnCode) {
                int returnCode3 = tmStatMfdMchntDayMapper.insertMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
                if (CommonConstant.PROCESS_SUCCESS != returnCode3) {
                    /* 插入数据失败 */
                    rglog.error("插入法人机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            } else {
                /* 更新数据失败 */
                rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
            }
        }

        //如果当规则不是0 ，则还需要更新规则为0的记录
        if (!CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStatMfdMchntDay.getRuleIndex())) {
            tmStatMfdMchntDay.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);

            int returnCode2 = tmStatMfdMchntDayMapper.updateMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
            if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                if (Database.DBS_NOT_FOUND == returnCode) {
                    int returnCode3 = tmStatMfdMchntDayMapper.insertMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode3) {
                        /* 插入数据失败 */
                        rglog.error("插入法人机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                } else {
                    /* 更新数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            }
        }
    }

    /**
     * 计算部分退款商户手续费应退优惠手续费和应退应收手续费
     *
     * @param dbsUtil                    数据库操作工具类
     * @param paymentReturnOrderInfoBean (合并)支付退货订单信息
     * @param tmTxnOrder                 订单流水信息
     * @param tmTxnOrderDet              订单明细信息
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/27 09:58
     */
    private void calculatePartiallyRefundFeeAmt(DbsUtil dbsUtil, PaymentReturnOrderInfoBean paymentReturnOrderInfoBean, TMTxnOrder tmTxnOrder, TMTxnOrderDet tmTxnOrderDet) throws Exception {

        String instId = tmTxnOrder.getInstId();
        String transDate = tmTxnOrder.getTxnDate();
        String mchntNo = tmTxnOrderDet.getMchntNo();
        String traceNo = tmTxnOrder.getFrontSeqNum();

        JsonMfdMcOrderRemark jsonMfdMcOrderRemark = JsonOperation.parseMfdMcOrderDetailOrderRemark(tmTxnOrderDet.getOrderRemark(), rglog);

        BigDecimal thousand = new BigDecimal(CommonConstant.THOUSAND);
        /* 商户订单金额 */
        BigDecimal origOrderAmt = new BigDecimal(jsonMfdMcOrderRemark.getOrderAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        /* 商户应收手续费 */
        BigDecimal origMchntFeeReceivable = new BigDecimal(jsonMfdMcOrderRemark.getMchntFeeReceivable()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        /* 实收手续费金额 */
        BigDecimal origMchntFeeActual;

        /* 本笔交易订单金额  取mchntsettle字段的金额值*/
        BigDecimal thisOrderAmt = new BigDecimal(paymentReturnOrderInfoBean.getMchntSettleAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        /* 本笔交易应退手续费 */
        BigDecimal thisMchntFeeReceivable = new BigDecimal(paymentReturnOrderInfoBean.getMchntFeeReceivable()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        /* 本交易应退优惠手续费 */
        BigDecimal thisFeeDiscount;
        /* 本交易实退手续费 */
        BigDecimal thisFeeActual;

        /* 商户应收手续费费率 */
        BigDecimal mchntFeeReceivableRate = BigDecimal.ZERO;
        String mchntFeeReceivableRateString = jsonMfdMcOrderRemark.getMchntFeeReceivableRate();
        if (null == mchntFeeReceivableRateString || "".equals(mchntFeeReceivableRateString)) {
            //获取原支付交易的源系统标识，迁移数据固定为“SJQY”
            String msgSrcId = tmTxnOrder.getMsgSrcId();
            //如果是迁移的数据，没有feeInputMode值正常
            if (CommonConstant.SHUJUQIANYI.equals(msgSrcId)) {
                rglog.info("本次退货原交易流水<{}> 为老平台迁移数据，原交易订单明细中mchntFeeReceivableRate为空", tmTxnOrder.getFrontSeqNum());
            } else {
                //不是迁移数据时，如果字段为空，则原交易存在问题
                rglog.error("本次退货原交易流水<{}> 原交易不是迁移数据，交易订单明细中mchntFeeReceivableRate为空，异常!", tmTxnOrder.getFrontSeqNum());
                throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
            }
        } else {
            /* 商户应收手续费费率 */
            mchntFeeReceivableRate = new BigDecimal(mchntFeeReceivableRateString).setScale(CommonConstant.DECIMAL_SCALE_FIVE, RoundingMode.HALF_UP);
        }

        //原交易优惠类型
        String discountType = jsonMfdMcOrderRemark.getDiscountType();
        //优惠力度
        String discountString = jsonMfdMcOrderRemark.getDiscount();

        /* 累计退货订单金额(包含本笔) */
        BigDecimal refundOrderAmtAfter;

        /* 累计应退手续费(不包含本笔) */
        BigDecimal refundMchntFeeBefore;
        /* 费率折扣 */
        BigDecimal discount;

        /* 原交易优惠的手续费 */
        BigDecimal mchntFeeDiscuont;
        /* 累计实退手续费金额 */
        BigDecimal alredayRefundMchntFee;
        /* min(剩余消费金额 * 营销费率，手续费封顶金额） */
        BigDecimal residueFeeMchntFee;
        /* 剩余消费金额 * 营销费率 */
        BigDecimal thisMchntFeeDiscount;

        /* 取已退货信息 */
        TMStatRefundMapper tmStatRefundMapper = new TMStatRefundMapperImpl();
        TMStatRefund tmStatRefund = tmStatRefundMapper.selectSingleRecordFromTMStatRefund(instId, transDate, traceNo, mchntNo);
        if (null == tmStatRefund) {
            rglog.info("本次交易流水<{}> 未取到退货记录，说明之前未有过部分退货订单!", globalTraceNo);
            /* 累计退货订单金额(包含本笔) */
            refundOrderAmtAfter = thisOrderAmt;
            if (!StringUtil.isNullorEmpty(discountType)) {
                /* 判断原始支付交易优惠类型 */
                switch (discountType) {
                    case CommonConstant.MCHNT_FEE_FREE:
                        rglog.info("本次交易流水<{}> 优惠类型discountType<{}> 手续费全免!", globalTraceNo, discountType);
                        /* 手续费全免,实收为0,优惠=应收 */
                        //原交易优惠的手续费
                        mchntFeeDiscuont = new BigDecimal(tmTxnOrderDet.getSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        //原交易实收手续费
                        origMchntFeeActual = origMchntFeeReceivable.subtract(mchntFeeDiscuont).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        thisFeeActual = origMchntFeeActual.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        thisFeeDiscount = thisMchntFeeReceivable.subtract(thisFeeActual).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        break;

                    case CommonConstant.MCHNT_FEE_DISCOUNT:
                        /* 费率打折,实收=应收*费率*折扣,优惠=应收-实收
                         * 实退手续费：消费时实收手续费 - 累计实退手续费 - min(剩余消费金额 * 费率 * 折扣，手续费封顶金额）
                         * 商户优惠手续费：应退手续费 - 实退手续费 */
                        //折扣
                        discount = new BigDecimal(discountString).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        rglog.info("本次交易流水<{}> 优惠类型discountType<{}> 费率打折，折扣<{}>!", globalTraceNo, discountType, discount);
                        //原交易优惠的手续费
                        mchntFeeDiscuont = new BigDecimal(tmTxnOrderDet.getSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        //原交易实收手续费
                        origMchntFeeActual = origMchntFeeReceivable.subtract(mchntFeeDiscuont).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        //剩余金额应收手续费
                        thisMchntFeeDiscount = (origOrderAmt.subtract(refundOrderAmtAfter)).multiply(mchntFeeReceivableRate).divide(thousand).multiply(discount).divide(BigDecimal.TEN).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        if (CommonConstant.ZERO >= thisMchntFeeDiscount.compareTo(origMchntFeeReceivable)) {
                            residueFeeMchntFee = thisMchntFeeDiscount;
                        } else {
                            residueFeeMchntFee = origMchntFeeReceivable;
                        }

                        thisFeeActual = origMchntFeeActual.subtract(residueFeeMchntFee).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        thisFeeDiscount = thisMchntFeeReceivable.subtract(thisFeeActual).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        break;

                    case CommonConstant.MCHNT_FEE_FIXED_RATE:
                        /* 固定费率,实收=订单金额*优惠费率,优惠=应收-实收
                         * 实退手续费：消费时实收手续费 - 累计实退手续费 - min(剩余消费金额 * 营销费率，手续费封顶金额)
                         * 商户优惠手续费：应退手续费 - 实退手续费 */
                        //固定费率值
                        discount = new BigDecimal(discountString).divide(thousand).setScale(CommonConstant.DECIMAL_SCALE_FIVE, RoundingMode.HALF_UP);
                        rglog.info("本次交易流水<{}> 优惠类型discountType<{}> 固定费率，费率<{}>!", globalTraceNo, discountType, discount);

                        //原交易优惠的手续费
                        mchntFeeDiscuont = new BigDecimal(tmTxnOrderDet.getSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        //原交易实收手续费
                        origMchntFeeActual = origMchntFeeReceivable.subtract(mchntFeeDiscuont).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        //剩余金额应收手续费
                        thisMchntFeeDiscount = (origOrderAmt.subtract(refundOrderAmtAfter)).multiply(discount).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        if (CommonConstant.ZERO >= thisMchntFeeDiscount.compareTo(origMchntFeeReceivable)) {
                            residueFeeMchntFee = thisMchntFeeDiscount;
                        } else {
                            residueFeeMchntFee = origMchntFeeReceivable;
                        }

                        thisFeeActual = origMchntFeeActual.subtract(residueFeeMchntFee).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        thisFeeDiscount = thisMchntFeeReceivable.subtract(thisFeeActual).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        break;

                    default:
                        rglog.error("原交易手续费优惠类型discountType错误！，应退优惠手续费和应退实收手续费计算失败,退货失败!");
                        dbsUtil.dbsEndTransaction(false);
                        throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
                }

                rglog.info("本次交易流水<{}> 手续费优惠计算结束，优惠手续费<{}> 实收手续费<{}>!", globalTraceNo, thisFeeDiscount.toString(), thisFeeActual.toString());

                paymentReturnOrderInfoBean.setMchntFeeDiscount(thisFeeDiscount.toString());
                paymentReturnOrderInfoBean.setMchntFeeActual(thisFeeActual.toString());

            } else {
                rglog.error("原交易手续费优惠类型discountType为空！，应退优惠手续费和应退实收手续费计算失败,退货失败!");
                dbsUtil.dbsEndTransaction(false);
                throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
            }

            //进入此函数的为部分退款，退货统计表中又没有已退货的累计信息，所以本笔退货肯定不是最后一笔退货
            isLastDeal = false;
        } else {
            rglog.info("本次交易流水<{}> 已取到退货记录，说明之前有过部分退货订单!", globalTraceNo);
            /* 判断是否是最后一笔退货 */
            /* 累计退货订单金额(不包含本笔) */
            BigDecimal refundOrderAmt = new BigDecimal(tmStatRefund.getRefundOrderAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            /* 累计退货订单金额(包含本笔) */
            refundOrderAmtAfter = thisOrderAmt.add(refundOrderAmt).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            //累计退货手续费费（不包含本笔）
            refundMchntFeeBefore = new BigDecimal(tmStatRefund.getRefundMchntFee()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

            //原交易优惠的手续费
            mchntFeeDiscuont = new BigDecimal(tmTxnOrderDet.getSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            //原交易实收手续费
            origMchntFeeActual = origMchntFeeReceivable.subtract(mchntFeeDiscuont).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

            if (CommonConstant.ZERO <= refundOrderAmtAfter.compareTo(origOrderAmt)) {
                /* 已超过可退货额度或最后一笔退货 */
                if (CommonConstant.ZERO == refundOrderAmtAfter.compareTo(origOrderAmt)) {
                    /* 最后一笔退货,无需进一步计算,直接使用统计值和本笔交易数据进行计算 */
                    rglog.info("当前累计退货订单金额(包含本笔退货订单金额)<{}>等于支付订单金额<{}>,本笔交易是最后一次退货!", refundOrderAmtAfter.toString(), origOrderAmt.toString());

                    //本次是最后一笔退款,实退为当初实收的减已经退的
                    thisFeeActual = origMchntFeeActual.subtract(refundMchntFeeBefore).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                    thisFeeDiscount = thisMchntFeeReceivable.subtract(thisFeeActual).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                    paymentReturnOrderInfoBean.setMchntFeeDiscount(thisFeeDiscount.toString());
                    paymentReturnOrderInfoBean.setMchntFeeActual(thisFeeActual.toString());

                    //部分退款，本笔退货是最后一笔退货
                    isLastDeal = true;
                } else {
                    /* 已超过可退货额度 */
                    rglog.error("当前累计退货订单金额(包含本笔退货订单金额)<{}>已超过支付订单金额<{}>,退货失败!", refundOrderAmtAfter.toString(), origOrderAmt.toString());
                    dbsUtil.dbsEndTransaction(false);
                    throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
                }
            } else {
                /* 非最后一笔部分退货，需要进行计算 */
                if (!StringUtil.isNullorEmpty(discountType)) {
                    /* 判断原始支付交易优惠类型 */
                    switch (discountType) {
                        case CommonConstant.MCHNT_FEE_FREE:
                            rglog.info("本次交易流水<{}> 优惠类型discountType<{}> 手续费全免!", globalTraceNo, discountType);
                            /* 手续费全免,实收为0,优惠=应收 */
                            //退货统计表中累计回退的手续费
                            alredayRefundMchntFee = new BigDecimal(tmStatRefund.getRefundMchntFee()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                            thisFeeActual = origMchntFeeActual.subtract(alredayRefundMchntFee).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            thisFeeDiscount = thisMchntFeeReceivable.subtract(thisFeeActual).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            break;

                        case CommonConstant.MCHNT_FEE_DISCOUNT:
                            /* 费率打折,实收=应收*费率*折扣,优惠=应收-实收
                             * 实退手续费：消费时实收手续费 - 累计实退手续费 - min(剩余消费金额 * 营销费率，手续费封顶金额)
                             * 商户优惠手续费：应退手续费 - 实退手续费 */
                            discount = new BigDecimal(discountString).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            rglog.info("本次交易流水<{}> 优惠类型discountType<{}> 费率打折，折扣<{}>!", globalTraceNo, discountType, discount);

                            //原交易优惠的手续费
                            mchntFeeDiscuont = new BigDecimal(tmTxnOrderDet.getSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            //原交易实收手续费
                            origMchntFeeActual = origMchntFeeReceivable.subtract(mchntFeeDiscuont).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            //退货统计表中累计回退的手续费
                            alredayRefundMchntFee = new BigDecimal(tmStatRefund.getRefundMchntFee()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            //剩余金额应收手续费
                            thisMchntFeeDiscount = (origOrderAmt.subtract(refundOrderAmtAfter)).multiply(mchntFeeReceivableRate).divide(thousand).multiply(discount).divide(BigDecimal.TEN).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                            if (CommonConstant.ZERO >= thisMchntFeeDiscount.compareTo(origMchntFeeReceivable)) {
                                residueFeeMchntFee = thisMchntFeeDiscount;
                            } else {
                                residueFeeMchntFee = origMchntFeeReceivable;
                            }

                            thisFeeActual = origMchntFeeActual.subtract(alredayRefundMchntFee).subtract(residueFeeMchntFee).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            thisFeeDiscount = thisMchntFeeReceivable.subtract(thisFeeActual).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            break;

                        case CommonConstant.MCHNT_FEE_FIXED_RATE:
                            /* 固定费率,实收=订单金额*优惠费率,优惠=应收-实收
                             * 实退手续费：消费时实收手续费 - 累计实退手续费 - min(剩余消费金额 * 营销费率，手续费封顶金额
                             * 商户优惠手续费：应退手续费 - 实退手续费 */
                            discount = new BigDecimal(discountString).divide(thousand).setScale(CommonConstant.DECIMAL_SCALE_FIVE, RoundingMode.HALF_UP);
                            rglog.info("本次交易流水<{}> 优惠类型discountType<{}> 固定费率，费率<{}>!", globalTraceNo, discountType, discount);
                            //原交易优惠的手续费
                            mchntFeeDiscuont = new BigDecimal(tmTxnOrderDet.getSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            //原交易实收手续费
                            origMchntFeeActual = origMchntFeeReceivable.subtract(mchntFeeDiscuont).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            //退货统计表中累计的已退手续费金额
                            alredayRefundMchntFee = new BigDecimal(tmStatRefund.getRefundMchntFee()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            //剩余金额应收手续费
                            thisMchntFeeDiscount = (origOrderAmt.subtract(refundOrderAmtAfter)).multiply(discount).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            if (CommonConstant.ZERO >= thisMchntFeeDiscount.compareTo(origMchntFeeReceivable)) {
                                residueFeeMchntFee = thisMchntFeeDiscount;
                            } else {
                                residueFeeMchntFee = origMchntFeeReceivable;
                            }

                            thisFeeActual = origMchntFeeActual.subtract(alredayRefundMchntFee).subtract(residueFeeMchntFee).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            thisFeeDiscount = thisMchntFeeReceivable.subtract(thisFeeActual).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            break;

                        default:
                            rglog.error("原交易手续费优惠类型discountType错误！，应退优惠手续费和应退实收手续费计算失败,退货失败!");
                            dbsUtil.dbsEndTransaction(false);
                            throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
                    }

                    rglog.info("本次交易流水<{}> 手续费优惠计算结束，优惠手续费<{}> 实收手续费!", globalTraceNo, thisFeeDiscount.toString(), thisFeeActual.toString());
                    paymentReturnOrderInfoBean.setMchntFeeDiscount(thisFeeDiscount.toString());
                    paymentReturnOrderInfoBean.setMchntFeeActual(thisFeeActual.toString());

                    //部分退款，本笔退货不是最后一笔退货
                    isLastDeal = false;

                } else {
                    rglog.error("原交易手续费优惠类型discountType为空！，应退优惠手续费和应退实收手续费计算失败,退货失败!");
                    dbsUtil.dbsEndTransaction(false);
                    throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
                }
            }
        }

        /* 根据已退货信息计算 */
        TMStatRefund tmStatRefund1 = new TMStatRefund();
        tmStatRefund1.setInstId(instId);
        tmStatRefund1.setTxnDate(tmTxnOrder.getTxnDate());
        tmStatRefund1.setTxnTime(tmTxnOrder.getTxnTime());
        tmStatRefund1.setSysSeqNum(tmTxnOrder.getFrontSeqNum());
        tmStatRefund1.setOrderId(tmTxnOrder.getOrderId());
        tmStatRefund1.setMchntNo(tmTxnOrderDet.getMchntNo());
        tmStatRefund1.setOrderCcy("CNY");
        tmStatRefund1.setMcType(tmTxnOrderDet.getMcType());
        tmStatRefund1.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());

        //判断是否是最后一笔退货
        if (isLastDeal) {
            tmStatRefund1.setBizStatus(BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode());
        } else {
            tmStatRefund1.setBizStatus(BizStatusEnum.PROCESS_PARTIALLY_REFUNDED.getBizStatusCode());
        }

        tmStatRefund1.setOrderAmt(origOrderAmt.toString());
        tmStatRefund1.setMchntFee(origMchntFeeReceivable.toString());
        tmStatRefund1.setMcNo(tmTxnOrderDet.getMcNo());
        tmStatRefund1.setRuleIndex(tmTxnOrderDet.getRuleIndex());
        tmStatRefund1.setRefundCount(CommonConstant.ONE_COMMON_CONSTANT);
        tmStatRefund1.setRefundOrderAmt(thisOrderAmt.toString());
        tmStatRefund1.setRefundMchntFee(thisFeeActual.toString());
        tmStatRefund1.setRefundSubsidy(thisFeeDiscount.toString());
        tmStatRefund1.setRefundBankSubsidy(thisFeeDiscount.toString());
        tmStatRefund1.setRefundMchntSubsidy(CommonConstant.ZERO_AMOUNT);
        tmStatRefund1.setOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStatRefund1.setCreateTime(globalTimeStamp);
        tmStatRefund1.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStatRefund1.setUpdateTime(globalTimeStamp);

        int returnCode = tmStatRefundMapper.updateSingleRecordFromTmStatRefund(tmStatRefund1);
        if (Database.DBS_NOT_FOUND == returnCode) {
            /* 更新到0条数据,需要插入数据 */
            returnCode = tmStatRefundMapper.insertSingleRecordFromTmStatRefund(tmStatRefund1);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                rglog.error("本次流水号<{}> 商户号<> 原交易流水号<{}> 插入部分退货信息失败,退货失败!", globalTraceNo, tmTxnOrderDet.getMchntNo(), tmTxnOrder.getFrontSeqNum());
                dbsUtil.dbsEndTransaction(false);
                throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
            } else {
                rglog.info("本次流水号<{}>计算部分退货金额成功!应退优惠手续费金额=<{}>, 实退手续费金额=<{}>", globalTraceNo, paymentReturnOrderInfoBean.getMchntFeeDiscount(), paymentReturnOrderInfoBean.getMchntFeeActual());
            }

        } else if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("本次流水号<{}> 商户号<> 原交易流水号<{}> 更新部分退货信息失败,退货失败!", globalTraceNo, tmTxnOrderDet.getMchntNo(), tmTxnOrder.getFrontSeqNum());
            dbsUtil.dbsEndTransaction(false);
            throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());

        } else {
            rglog.info("计算部分退货金额成功!应退优惠手续费金额=<{}>, 实退手续费金额=<{}>", paymentReturnOrderInfoBean.getMchntFeeDiscount(), paymentReturnOrderInfoBean.getMchntFeeActual());
        }
    }


    /**
     * 处理商户手续费营销活动部分回退统计数据
     *
     * @param dbsUtil                    数据库操作工具类
     * @param paymentReturnOrderInfoBean (合并)支付退货订单信息对象
     * @param tmTxnOrderDet              订单明细
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/27 09:51
     */
    private void reversePartiallyMchntFeeDiscountMcStatistics(DbsUtil dbsUtil, PaymentReturnOrderInfoBean paymentReturnOrderInfoBean, TMTxnOrderDet tmTxnOrderDet, String mchntNo) throws Exception {

        /* 更新手续费减免活动单日统计表数据 */
        TMStatMfdDay tmStatMfdDay = new TMStatMfdDay();

        tmStatMfdDay.setInstId(tmTxnOrderDet.getInstId());
        tmStatMfdDay.setMcNo(tmTxnOrderDet.getMcNo());
        tmStatMfdDay.setTxnDate(globalTxnDate);
        tmStatMfdDay.setRuleIndex(tmTxnOrderDet.getRuleIndex());

        BigDecimal minusOne = BigDecimal.ZERO.subtract(BigDecimal.ONE);
        String minusOneString = minusOne.toString();
        String totalSubsidy = new BigDecimal(paymentReturnOrderInfoBean.getMchntFeeDiscount()).multiply(minusOne).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
        String orderAmt = new BigDecimal(paymentReturnOrderInfoBean.getMchntSettleAmt()).multiply(minusOne).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();

        //如果是最后一笔交易，则更新笔数，否则不更新
        if (isLastDeal) {
            rglog.info("本笔退货交易是最后一笔退款，需要更新统计表中的累计交易笔数字段");
            tmStatMfdDay.setTotalQtyAcc(minusOneString);
            tmStatMfdDay.setTxnQtyAcc(minusOneString);
        } else {
            rglog.info("本笔退货交易不是最后一笔退款，不需要更新统计表中的累计交易笔数字段");
            tmStatMfdDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }
        tmStatMfdDay.setTotalAmtAcc(totalSubsidy);
        tmStatMfdDay.setTxnAmtAcc(orderAmt);

        tmStatMfdDay.setMchntQty(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdDay.setMchntOldQualified(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdDay.setMchntNewQualified(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdDay.setMchntExitQty(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdDay.setAvgAmt(CommonConstant.ZERO_AMOUNT);
        tmStatMfdDay.setPaidAmt(CommonConstant.ZERO_AMOUNT);
        tmStatMfdDay.setOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStatMfdDay.setCreateTime(globalTimeStamp);
        tmStatMfdDay.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStatMfdDay.setUpdateTime(globalTimeStamp);

        TMStatMfdDayMapper tmStatMfdDayMapper = new TMStatMfdDayMapperImpl();
        int returnCode = tmStatMfdDayMapper.updateMchntFeeDiscountDayStatistics(tmStatMfdDay);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            if (Database.DBS_NOT_FOUND == returnCode) {
                int returnCode2 = tmStatMfdDayMapper.insertTMStatMfdDay(tmStatMfdDay);
                if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                    /* 插入数据失败 */
                    rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            } else {
                /* 更新数据失败 */
                rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
            }
        }
        //如果当规则不是0 ，则还需要更新规则为0的记录
        if (!CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStatMfdDay.getRuleIndex())) {
            tmStatMfdDay.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);

            returnCode = tmStatMfdDayMapper.updateMchntFeeDiscountDayStatistics(tmStatMfdDay);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                if (Database.DBS_NOT_FOUND == returnCode) {
                    int returnCode2 = tmStatMfdDayMapper.insertTMStatMfdDay(tmStatMfdDay);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                        /* 插入数据失败 */
                        rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                } else {
                    /* 更新数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            }
        }

        /* 更新手续费减免活动商户单日统计表 */
        TMStatMfdMchntDay tmStatMfdMchntDay = new TMStatMfdMchntDay();
        tmStatMfdMchntDay.setInstId(tmTxnOrderDet.getInstId());
        tmStatMfdMchntDay.setMcNo(tmTxnOrderDet.getMcNo());
        tmStatMfdMchntDay.setTxnDate(globalTxnDate);
        tmStatMfdMchntDay.setMchntNo(mchntNo);
        tmStatMfdMchntDay.setRuleIndex(tmTxnOrderDet.getRuleIndex());

        //如果是最后一笔交易，则更新笔数，否则不更新
        if (isLastDeal) {
            tmStatMfdMchntDay.setTotalQtyAcc(minusOneString);
            tmStatMfdMchntDay.setTxnQtyAcc(minusOneString);
        } else {
            tmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }
        tmStatMfdMchntDay.setTotalAmtAcc(totalSubsidy);
        tmStatMfdMchntDay.setTxnAmtAcc(orderAmt);

        tmStatMfdMchntDay.setTotalAvgAmt(CommonConstant.ZERO_AMOUNT);
        tmStatMfdMchntDay.setExitStatus(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdMchntDay.setCashbackStatus(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdMchntDay.setCashbackAmt(CommonConstant.ZERO_AMOUNT);
        tmStatMfdMchntDay.setOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStatMfdMchntDay.setCreateTime(globalTimeStamp);
        tmStatMfdMchntDay.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStatMfdMchntDay.setUpdateTime(globalTimeStamp);

        TMStatMfdMchntDayMapper tmStatMfdMchntDayMapper = new TMStatMfdMchntDayMapperImpl();
        returnCode = tmStatMfdMchntDayMapper.updateMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            if (Database.DBS_NOT_FOUND == returnCode) {
                int returnCode3 = tmStatMfdMchntDayMapper.insertMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
                if (CommonConstant.PROCESS_SUCCESS != returnCode3) {
                    /* 插入数据失败 */
                    rglog.error("插入法人机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            } else {
                /* 更新数据失败 */
                rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
            }
        }

        //如果当规则不是0 ，则还需要更新规则为0的记录
        if (!CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStatMfdMchntDay.getRuleIndex())) {
            tmStatMfdMchntDay.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);

            int returnCode2 = tmStatMfdMchntDayMapper.updateMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
            if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                if (Database.DBS_NOT_FOUND == returnCode) {
                    int returnCode3 = tmStatMfdMchntDayMapper.insertMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode3) {
                        /* 插入数据失败 */
                        rglog.error("插入法人机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                } else {
                    /* 更新数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            }
        }
    }

    /**
     * 回退订单明细数据
     *
     * @param dbsUtil       数据库操作工具类
     * @param tmTxnOrderDet 订单明细表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/26 17:57
     */
    private void reverseTxnOrderDetail(DbsUtil dbsUtil, TMTxnOrderDet tmTxnOrderDet) throws Exception {

        TMTxnOrderDetMapper tmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
        int returnCode = tmTxnOrderDetMapper.updateSingleOriginalTransactionOrderDetailStatusInfo(tmTxnOrderDet);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("更新法人机构<>在<{}>的流水号<{}>的订单明细失败", tmTxnOrderDet.getInstId(), tmTxnOrderDet.getTxnDate(), tmTxnOrderDet.getFrontSeqNum());
//            dbsUtil.dbsEndTransaction(false);
            throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
        }
    }

    /**
     * 插入退货交易流水
     *
     * @param dbsUtil                   数据库操作工具类
     * @param comboPaymentRefundRequest (合并)支付退货接口请求对象
     * @param tmTxnOrder                订单流水表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/6/12 00:37
     */
    private void insertSingleRecordIntoTMTxnOrder(DbsUtil dbsUtil, ComboPaymentRefundRequest comboPaymentRefundRequest, TMTxnOrder tmTxnOrder) throws Exception {

        TMTxnOrder tmTxnOrder1 = new TMTxnOrder();
        tmTxnOrder1.setInstId(globalInstId);
        tmTxnOrder1.setTxnDate(globalTxnDate);
        tmTxnOrder1.setTxnTime(globalTransTime);
        tmTxnOrder1.setTxnNum(comboPaymentRefundRequest.getHeader().getTxnNum());
        tmTxnOrder1.setBizType(comboPaymentRefundRequest.getHeader().getBizType());
        tmTxnOrder1.setBizProdCode(tmTxnOrder.getBizProdCode());
        tmTxnOrder1.setMsgSrcId(comboPaymentRefundRequest.getHeader().getSrcSysId());
        tmTxnOrder1.setFrontSeqNum(globalTraceNo);
        tmTxnOrder1.setOrderId(comboPaymentRefundRequest.getMchntOrderId());
        tmTxnOrder1.setUserId(tmTxnOrder.getUserId());

        if (CommonConstant.REFUND_TYPE_ALL.equals(refundType)) {
            /* 全额退款,报文内容和原支付交易内容相同 */
            tmTxnOrder1.setOrderAmt(tmTxnOrder.getOrderAmt());
            tmTxnOrder1.setTxnAmt(tmTxnOrder.getTxnAmt());
            tmTxnOrder1.setSubsidyAmt(tmTxnOrder.getSubsidyAmt());
            tmTxnOrder1.setBankSubsidyAmt(tmTxnOrder.getBankSubsidyAmt());
            tmTxnOrder1.setMchntSubsidyAmt(tmTxnOrder.getMchntSubsidyAmt());
        } else {
            /* 部分退款,优惠部分为0,其他和退货金额相同 */
            tmTxnOrder1.setOrderAmt(comboPaymentRefundRequest.getReturnAmt());
            tmTxnOrder1.setTxnAmt(comboPaymentRefundRequest.getReturnAmt());
            tmTxnOrder1.setSubsidyAmt(CommonConstant.ZERO_AMOUNT);
            tmTxnOrder1.setBankSubsidyAmt(CommonConstant.ZERO_AMOUNT);
            tmTxnOrder1.setMchntSubsidyAmt(CommonConstant.ZERO_AMOUNT);
        }

        tmTxnOrder1.setOrigTxnDate(comboPaymentRefundRequest.getOrigTxnDate());
        tmTxnOrder1.setOrigSysSeqNum(comboPaymentRefundRequest.getOrigTraceNo());
        tmTxnOrder1.setOrigOrderId(tmTxnOrder.getOrderId());

        tmTxnOrder1.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
        tmTxnOrder1.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
        tmTxnOrder1.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);

        if (!globalTMTxnOrderDetList.isEmpty()) {
            BigDecimal subsidyAmt = BigDecimal.ZERO;
            for (TMTxnOrderDet tmTxnOrderDet : globalTMTxnOrderDetList) {
                subsidyAmt = subsidyAmt.add(new BigDecimal(tmTxnOrderDet.getSubsidy()).abs());
            }
            //订单预留信息  所有的订单的优惠手续费大于0时，本笔订单流水登记有优惠且参与对账
            if (subsidyAmt.compareTo(BigDecimal.ZERO) > CommonConstant.ZERO) {
                tmTxnOrder1.setOrderRemark(CommonConstant.DISCOUNT_FLAG_TRUE_CHECK_FLAG_TRUE);
            } else {
                tmTxnOrder1.setOrderRemark(CommonConstant.DISCOUNT_FLAG_TRUE_CHECK_FLAG_FALSE);
            }
        } else {
            tmTxnOrder1.setOrderRemark(CommonConstant.DISCOUNT_FLAG_FALSE_CHECK_FLAG_FALSE);
        }

        tmTxnOrder1.setOprId(CommonConstant.DEFAULT_OPR_ID);
        tmTxnOrder1.setCreateTime(globalTimeStamp);

        TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();
        int returnCode = tmTxnOrderMapper.insertSingleRecordIntoTMTxnOrder(tmTxnOrder1);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            /* 插入本笔退货交易流水失败 */
//            dbsUtil.dbsEndTransaction(false);
            rglog.error("插入法人机构号<{}>在<{}>的流水号<{}>的退货交易流水失败! RETURN_CODE=<{}>", globalInstId, globalTxnDate, globalTraceNo, returnCode);
            throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
        }
        rglog.info("插入法人机构<{}> 交易日期<{}> 流水号<{}> 的退货交易流水成功!", globalInstId, globalTxnDate, globalTraceNo);
    }

    /**
     * 插入退货交易流水（原交易没有营销）
     *
     * @param dbsUtil                   数据库操作工具类
     * @param comboPaymentRefundRequest (合并)支付退货接口请求对象
     * @param tmTxnOrder                订单流水表
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/8/28 09:54
     */
    private void insertSingleRecordIntoTMTxnOrderFalse(DbsUtil dbsUtil, ComboPaymentRefundRequest comboPaymentRefundRequest, TMTxnOrder tmTxnOrder) throws Exception {

        TMTxnOrder tmTxnOrder1 = new TMTxnOrder();
        tmTxnOrder1.setInstId(globalInstId);
        tmTxnOrder1.setTxnDate(globalTxnDate);
        tmTxnOrder1.setTxnTime(globalTransTime);
        tmTxnOrder1.setTxnNum(comboPaymentRefundRequest.getHeader().getTxnNum());
        tmTxnOrder1.setBizType(comboPaymentRefundRequest.getHeader().getBizType());
        tmTxnOrder1.setBizProdCode(tmTxnOrder.getBizProdCode());
        tmTxnOrder1.setMsgSrcId(comboPaymentRefundRequest.getHeader().getSrcSysId());
        tmTxnOrder1.setFrontSeqNum(globalTraceNo);
        tmTxnOrder1.setOrderId(globalOrderId);
        tmTxnOrder1.setUserId(tmTxnOrder.getUserId());
        //订单金额
        tmTxnOrder1.setOrderAmt(tmTxnOrder.getOrderAmt());
        //实际支付金额
        tmTxnOrder1.setTxnAmt(tmTxnOrder.getTxnAmt());
        //总补贴金额
        tmTxnOrder1.setSubsidyAmt(CommonConstant.ZERO_AMOUNT);
        //机构补贴金额
        tmTxnOrder1.setBankSubsidyAmt(CommonConstant.ZERO_AMOUNT);
        //商户补贴金额
        tmTxnOrder1.setMchntSubsidyAmt(CommonConstant.ZERO_AMOUNT);

        tmTxnOrder1.setOrigTxnDate(comboPaymentRefundRequest.getOrigTxnDate());
        tmTxnOrder1.setOrigSysSeqNum(comboPaymentRefundRequest.getOrigTraceNo());
        tmTxnOrder1.setOrigOrderId(tmTxnOrder.getOrderId());

        tmTxnOrder1.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
        tmTxnOrder1.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
        tmTxnOrder1.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
        tmTxnOrder1.setOrderRemark(CommonConstant.DISCOUNT_FLAG_FALSE_CHECK_FLAG_FALSE);
        tmTxnOrder1.setOprId(CommonConstant.DEFAULT_OPR_ID);
        tmTxnOrder1.setCreateTime(globalTimeStamp);

        TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();
        int returnCode = tmTxnOrderMapper.insertSingleRecordIntoTMTxnOrder(tmTxnOrder1);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            /* 插入本笔退货交易流水失败 */
            dbsUtil.dbsEndTransaction(false);
            rglog.error("插入法人机构号<{}>在<{}>的流水号<{}>的退货交易流水失败! RETURN_CODE=<{}>", globalInstId, globalTxnDate, globalTraceNo, returnCode);
            throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
        }
        rglog.info("插入法人机构号<{}>在<{}>的流水号<{}>的退货交易流水成功!", globalInstId, globalTxnDate, globalTraceNo);
    }


    /**
     * 更新原支付交易流水
     *
     * @param dbsUtil    数据库操作工具类
     * @param tmTxnOrder 订单流水表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/6/12 00:49
     */
    private void updateOrigTxnOrderInfo(DbsUtil dbsUtil, TMTxnOrder tmTxnOrder) throws Exception {

        Boolean isOrderFullRefund = true;
        /* 查询原交易订单明细信息 */
        List<TMTxnOrderDet> tmTxnOrderDetList = getOriginalTransactionOrderDetailInfo(globalInstId, origTxnDate, origTraceNo);
        if (null == tmTxnOrderDetList || tmTxnOrderDetList.isEmpty()) {
            rglog.error("机构<{}>在<{}>的原交易订单明细信息<{}>失败!", globalInstId, origTxnDate, origTraceNo);
            dbsUtil.dbsEndTransaction(false);
            throw new BizException(RespCodeEnum.FAILED_TO_CHECK_ORIGINAL_TXNDET_INFO_ERROR.getRespCode(), RespCodeEnum.FAILED_TO_CHECK_ORIGINAL_TXNDET_INFO_ERROR.getRespDesc());
        }
        //循环遍历原订单流水对应的订单明细信息，如果状态都为已全额退款，则更新原交易流水为已全额退款，否则为部分退款
        for (TMTxnOrderDet tMTxnOrderDet : tmTxnOrderDetList) {
            if (!BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode().equals(tMTxnOrderDet.getBizStatus())) {
                isOrderFullRefund = false;
                break;
            }
        }

        if (isOrderFullRefund) {
            /* 全额退款,报文内容和原支付交易内容相同 */
            tmTxnOrder.setBizStatus(BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode());
        } else {
            /* 部分退款,优惠部分为0,其他和退货金额相同 */
            tmTxnOrder.setBizStatus(BizStatusEnum.PROCESS_PARTIALLY_REFUNDED.getBizStatusCode());
        }
        tmTxnOrder.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmTxnOrder.setUpdateTime(globalTimeStamp);

        TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();
        int returnCode = tmTxnOrderMapper.updateOriginalTransactionOrderBizStatus(tmTxnOrder);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            /* 更新原支付交易流水失败 */
//            dbsUtil.dbsEndTransaction(false);
            rglog.error("更新法人机构号<{}> 日期<{}> 流水号<{}> 的支付交易流水失败! RETURN_CODE=<{}>", tmTxnOrder.getInstId(), tmTxnOrder.getTxnDate(), tmTxnOrder.getFrontSeqNum(), returnCode);
            throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
        }
        rglog.info("更新法人机构号<{}> 日期<{}> 流水号<{}> 的支付交易流水成功!", tmTxnOrder.getInstId(), tmTxnOrder.getTxnDate(), tmTxnOrder.getFrontSeqNum());
    }

    /**
     * 更新原支付交易流水（原交易没有营销）
     *
     * @param dbsUtil    数据库操作工具类
     * @param tmTxnOrder 订单流水表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/8/28 10:09
     */
    private void updateOrigTxnOrderInfoFalse(DbsUtil dbsUtil, TMTxnOrder tmTxnOrder) throws Exception {

        //根据全额退款还是部分退款更新原订单状态
        if (CommonConstant.REFUND_TYPE_ALL.equals(refundType)) {
            tmTxnOrder.setBizStatus(BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode());
        } else {
            tmTxnOrder.setBizStatus(BizStatusEnum.PROCESS_PARTIALLY_REFUNDED.getBizStatusCode());
        }

        tmTxnOrder.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmTxnOrder.setUpdateTime(globalTimeStamp);

        TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();
        int returnCode = tmTxnOrderMapper.updateOriginalTransactionOrderBizStatus(tmTxnOrder);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            /* 更新原支付交易流水失败 */
            dbsUtil.dbsEndTransaction(false);
            rglog.error("更新法人机构号<{}> 日期<{}> 流水号<{}>的支付交易流水失败! RETURN_CODE=<{}>", tmTxnOrder.getInstId(), tmTxnOrder.getTxnDate(), tmTxnOrder.getFrontSeqNum(), returnCode);
            throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
        }
        rglog.info("更新法人机构号<{}> 日期<{}> 流水号<{}> 的支付交易流水成功!", tmTxnOrder.getInstId(), tmTxnOrder.getTxnDate(), tmTxnOrder.getFrontSeqNum());
    }

    /**
     * 订单明细记录数据准备
     *
     * @param object        营销活动交易信息数据对象
     * @param tmTxnOrderDet 订单明细表
     * @return cc.rengu.igas.momp.common.entity.TMTxnOrderDet 订单明细表
     * @author Jinan Liu
     * @since 2020/6/12 00:53
     */
    private TMTxnOrderDet convertTxnOrderDetail(Object object, TMTxnOrderDet tmTxnOrderDet) {
        TMTxnOrderDet tmTxnOrderDet1 = new TMTxnOrderDet();

        String mcType = tmTxnOrderDet.getMcType();
        if (McTypeEnum.MC_TYPE_MO.getMcTypeCode().equals(mcType.substring(0, 1))) {
            rglog.info("法人机构<{}> 流水号<{}> 商户<{}> 本笔交易满减订单明细数据准备...", globalInstId, globalTxnDate, globalTraceNo);
            /* 满减订单明细数据准备 */
            tmTxnOrderDet1.setInstId(globalInstId);
            tmTxnOrderDet1.setTxnDate(globalTxnDate);
            tmTxnOrderDet1.setFrontSeqNum(globalTraceNo);
            tmTxnOrderDet1.setOrderId(globalOrderId);
            tmTxnOrderDet1.setMchntNo(tmTxnOrderDet.getMchntNo());
            tmTxnOrderDet1.setUserId(tmTxnOrderDet.getUserId());
            tmTxnOrderDet1.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
            tmTxnOrderDet1.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
            tmTxnOrderDet1.setMcType(tmTxnOrderDet.getMcType());
            tmTxnOrderDet1.setOriginalAmt(tmTxnOrderDet.getOriginalAmt());
            tmTxnOrderDet1.setMcNo(tmTxnOrderDet.getMcNo());
            tmTxnOrderDet1.setRuleIndex(tmTxnOrderDet.getRuleIndex());
            tmTxnOrderDet1.setSubsidy(tmTxnOrderDet.getSubsidy());
            tmTxnOrderDet1.setBankSubsidy(tmTxnOrderDet.getBankSubsidy());
            tmTxnOrderDet1.setMchntSubsidy(tmTxnOrderDet.getMchntSubsidy());
            tmTxnOrderDet1.setRelativeData("{}");
            tmTxnOrderDet1.setOrderRemark("{}");
            tmTxnOrderDet1.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmTxnOrderDet1.setCreateTime(globalTimeStamp);

        } else if (McTypeEnum.MC_TYPE_MFD.getMcTypeCode().equals(mcType.substring(0, 1))) {

            PaymentReturnOrderInfoBean paymentReturnOrderInfoBean = (PaymentReturnOrderInfoBean) object;
            rglog.info("法人机构<{}> 流水号<{}> 商户<{}> 本笔交易手续费优惠订单明细数据准备...", globalInstId, globalTxnDate, globalTraceNo);
            /* 手续费优惠订单明细数据准备 */
            tmTxnOrderDet1.setInstId(globalInstId);
            tmTxnOrderDet1.setTxnDate(globalTxnDate);
            tmTxnOrderDet1.setFrontSeqNum(globalTraceNo);
            tmTxnOrderDet1.setOrderId(globalOrderId);
            tmTxnOrderDet1.setMchntNo(tmTxnOrderDet.getMchntNo());
            tmTxnOrderDet1.setUserId(tmTxnOrderDet.getUserId());
            tmTxnOrderDet1.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
            tmTxnOrderDet1.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
            tmTxnOrderDet1.setMcType(tmTxnOrderDet.getMcType());
            tmTxnOrderDet1.setOriginalAmt(paymentReturnOrderInfoBean.getMchntFeeReceivable());
            tmTxnOrderDet1.setMcNo(tmTxnOrderDet.getMcNo());
            tmTxnOrderDet1.setRuleIndex(tmTxnOrderDet.getRuleIndex());
            tmTxnOrderDet1.setSubsidy(paymentReturnOrderInfoBean.getMchntFeeDiscount());
            tmTxnOrderDet1.setBankSubsidy(paymentReturnOrderInfoBean.getMchntFeeDiscount());
            tmTxnOrderDet1.setMchntSubsidy(CommonConstant.ZERO_AMOUNT);

            //关联信息
            String oriRelativeData = tmTxnOrderDet.getRelativeData();
            JSONObject oriRelativeDataJson = JSONObject.parseObject(oriRelativeData);

            JSONObject relativeDataJson = new JSONObject();
            //退货订单金额
            relativeDataJson.put("orderAmt", paymentReturnOrderInfoBean.getOrderAmt());
            //退货商户应收手续费
            relativeDataJson.put("mchntFeeReceivable", paymentReturnOrderInfoBean.getMchntFeeReceivable());

            //原手续费优惠交易订单金额
            String origOrderAmt = oriRelativeDataJson.get("orderAmt").toString();
            relativeDataJson.put("origOrderAmt", origOrderAmt);
            //原手续费优惠交易手续费金额
            String origMchntFee = oriRelativeDataJson.get("mchntFeeReceivable").toString();
            relativeDataJson.put("origMchntFee", origMchntFee);

            //手续费收取方式
            Object feeInputMode = oriRelativeDataJson.get("feeInputMode");
            //商户手续费优惠类型
            String discountType = oriRelativeDataJson.get("discountType").toString();
            //优惠力度
            BigDecimal discount = new BigDecimal(oriRelativeDataJson.get("discount").toString());

            //手续费收取方式
            relativeDataJson.put("feeInputMode", feeInputMode);
            //商户手续费优惠类型
            relativeDataJson.put("discountType", discountType);
            //优惠力度
            relativeDataJson.put("discount", discount);

            String relativeData = relativeDataJson.toString();
            //关联信息
            tmTxnOrderDet1.setRelativeData(relativeData);
            //订单预留信息
            tmTxnOrderDet1.setOrderRemark(relativeData);

            tmTxnOrderDet1.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmTxnOrderDet1.setCreateTime(globalTimeStamp);

            String disTxAmt = tmTxnOrderDet.getDisTxAmt();
            BigDecimal oriDisTxAmt;
            BigDecimal origOrderAmtBigdecimal = new BigDecimal(origOrderAmt);
            BigDecimal mchntFeeDiscount = new BigDecimal(paymentReturnOrderInfoBean.getMchntFeeDiscount());
            if (null != disTxAmt) {
                oriDisTxAmt = new BigDecimal(disTxAmt);
            } else {
                oriDisTxAmt = origOrderAmtBigdecimal;
            }
            //如果原订单金额和优惠交易金额相同，则 原交易不是商户最后一笔非全额优惠，则本笔优惠交易金额和本笔上送的优惠交易金额相同
            if (oriDisTxAmt.compareTo(origOrderAmtBigdecimal) == 0) {
                //如果当前是最后部分退货的最后一笔退款，或者是全额退款，如果本笔交易有手续费优惠，则
                if (mchntFeeDiscount.compareTo(BigDecimal.ZERO) > 0) {
                    tmTxnOrderDet1.setDisTxAmt(paymentReturnOrderInfoBean.getOrderAmt());
                } else {
                    //如果没有手续费优惠，则本笔优惠交易金额为0
                    tmTxnOrderDet1.setDisTxAmt(CommonConstant.ZERO_AMOUNT);
                }
            } else {
                //如果不相同，则原交易为此商户最后一笔非全金额手续费优惠,只有当最后一笔退款时登记优惠交易金额，其他时候为0
                if (isLastDeal) {
                    tmTxnOrderDet1.setDisTxAmt(tmTxnOrderDet.getDisTxAmt());
                    //使用remark1标识，此订单虽然没有手续费优惠但是需要登记订单明细（有优惠交易金额）
                    tmTxnOrderDet1.setRemark1(CommonConstant.ONE_COMMON_CONSTANT);
                } else {
                    tmTxnOrderDet1.setDisTxAmt(CommonConstant.ZERO_AMOUNT);
                }
            }

        } else if (McTypeEnum.MC_TYPE_CP.getMcTypeCode().equals(mcType.substring(0, 1))) {
            rglog.info("法人机构<{}> 流水号<{}> 商户<{}> 本笔交易卡券订单明细数据准备...", globalInstId, globalTxnDate, globalTraceNo);
            /* 卡券订单明细数据准备 */
            tmTxnOrderDet1.setInstId(globalInstId);
            tmTxnOrderDet1.setTxnDate(globalTxnDate);
            tmTxnOrderDet1.setFrontSeqNum(globalTraceNo);
            tmTxnOrderDet1.setOrderId(globalOrderId);
            tmTxnOrderDet1.setMchntNo(tmTxnOrderDet.getMchntNo());
            tmTxnOrderDet1.setUserId(tmTxnOrderDet.getUserId());
            tmTxnOrderDet1.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
            tmTxnOrderDet1.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
            tmTxnOrderDet1.setMcType(tmTxnOrderDet.getMcType());
            tmTxnOrderDet1.setOriginalAmt(tmTxnOrderDet.getOriginalAmt());
            tmTxnOrderDet1.setMcNo(tmTxnOrderDet.getMcNo());
            tmTxnOrderDet1.setRuleIndex(tmTxnOrderDet.getRuleIndex());
            tmTxnOrderDet1.setSubsidy(tmTxnOrderDet.getSubsidy());
            tmTxnOrderDet1.setBankSubsidy(tmTxnOrderDet.getBankSubsidy());
            tmTxnOrderDet1.setMchntSubsidy(tmTxnOrderDet.getMchntSubsidy());
            tmTxnOrderDet1.setRelativeData("{}");
            tmTxnOrderDet1.setOrderRemark("{}");
            tmTxnOrderDet1.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmTxnOrderDet1.setCreateTime(globalTimeStamp);
        } else {
            rglog.error("错误的参数类型! CLASS=><{}>", object.getClass());
            return null;
        }

        return tmTxnOrderDet1;
    }

    /**
     * 全局变量赋值
     *
     * @param comboPaymentRefundRequest (合并)支付退货接口请求对象
     * @throws BizException 异常信息
     * @author liujinan
     * @date 2020/8/28 16:37
     */
    private void messageValidation(ComboPaymentRefundRequest comboPaymentRefundRequest) throws BizException {

        // 检查上传字段 不能为负数
        /*交易金额*/
        if (!StringUtil.isNullorEmpty(comboPaymentRefundRequest.getTransAmt()) && new BigDecimal(comboPaymentRefundRequest.getTransAmt()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /*退货金额*/
        if (!StringUtil.isNullorEmpty(comboPaymentRefundRequest.getReturnAmt()) && new BigDecimal(comboPaymentRefundRequest.getReturnAmt()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }

        globalTMTxnOrderDetList = new ArrayList<>();

        globalTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());

        if (StringUtil.isNullorEmpty(comboPaymentRefundRequest.getHeader().getInstId())) {
            rglog.error("法人机构号必须上送!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        } else {
            globalInstId = comboPaymentRefundRequest.getHeader().getInstId();
        }

        if (StringUtil.isNullorEmpty(comboPaymentRefundRequest.getHeader().getTransDate())) {
            rglog.error("交易日期必须上送!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        } else {
            globalTxnDate = comboPaymentRefundRequest.getHeader().getTransDate();
        }

        if (StringUtil.isNullorEmpty(comboPaymentRefundRequest.getHeader().getTransTime())) {
            rglog.error("交易时间必须上送!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        } else {
            globalTransTime = comboPaymentRefundRequest.getHeader().getTransTime();
        }

        if (StringUtil.isNullorEmpty(comboPaymentRefundRequest.getHeader().getTraceNo())) {
            rglog.error("流水号必须上送!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        } else {
            globalTraceNo = comboPaymentRefundRequest.getHeader().getTraceNo();
        }

        if (!StringUtil.isNullorEmpty(comboPaymentRefundRequest.getMchntOrderId())) {
            globalOrderId = comboPaymentRefundRequest.getMchntOrderId();
        } else {
            rglog.error("需要上送商户订单号!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (!StringUtil.isNullorEmpty(comboPaymentRefundRequest.getUserId())) {
            globalUserId = comboPaymentRefundRequest.getUserId();
        } else {
            rglog.error("需要上送用户标识!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (!StringUtil.isNullorEmpty(comboPaymentRefundRequest.getOrigTxnDate())) {
            origTxnDate = comboPaymentRefundRequest.getOrigTxnDate();
        } else {
            rglog.error("需要上送原交易日期!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (!StringUtil.isNullorEmpty(comboPaymentRefundRequest.getOrigTraceNo())) {
            origTraceNo = comboPaymentRefundRequest.getOrigTraceNo();
        } else {
            rglog.error("需要上送原交易流水!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (!StringUtil.isNullorEmpty(comboPaymentRefundRequest.getOrigTrialTraceNo())) {
            origTrialTraceNo = comboPaymentRefundRequest.getOrigTrialTraceNo();
            rglog.info("请求上送的原交易回退试算流水号<{}>", origTrialTraceNo);
        }

        if (!StringUtil.isNullorEmpty(comboPaymentRefundRequest.getOrigTrialTxnDate())) {
            origTrialTxnDate = comboPaymentRefundRequest.getOrigTrialTxnDate();
            rglog.info("请求上送的原交易回退试算日期<{}>", origTrialTxnDate);
        }
    }

    /**
     * 处理单个商户的商户手续费优惠营销活动 已经过试算的直接取数据
     *
     * @param dbsUtil                    数据库操作工具类
     * @param tmTxnOrder                 订单流水信息
     * @param paymentReturnOrderInfoBean (合并)支付退货订单信息
     * @param tmTxnOrderDetList          订单明细列表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/8/28 18:11
     */
    private void processSingleToMchntRefundProcedureAlreadyTrial(DbsUtil dbsUtil, TMTxnOrder tmTxnOrder, PaymentReturnOrderInfoBean paymentReturnOrderInfoBean,
                                                                 List<TMTxnOrderDet> tmTxnOrderDetList, TMTxnOrder OriTrialTmTxnOrder, List<TMTxnOrderDet> oriTrialTmTxnOrderDetList) throws Exception {
        String transDate = tmTxnOrder.getTxnDate();
        String mchntNo = paymentReturnOrderInfoBean.getMchntNo();

        /* 取原交易订单明细 */
        List<TMTxnOrderDet> oriTmTxnOrderDetListMdf = tmTxnOrderDetList.stream().filter(item -> ((McTypeEnum.MC_TYPE_MFD.getMcTypeCode().equals(item.getMcType().substring(0, 1))) && mchntNo.equals(item.getMchntNo()))).collect(Collectors.toList());
        if (oriTmTxnOrderDetListMdf.isEmpty()) {
            rglog.error("法人机构<{}> 交易日期<{}> 原交易流水<{}> 商户<{}> 对应的商户手续费优惠订单明细为0条,继续处理下一条退款明细!",
                    globalInstId, transDate, origTraceNo, mchntNo);
            return;
        }

        /* 取原试算订单明细 */
        List<TMTxnOrderDet> oriTrialTmTxnOrderDetListMdf = oriTrialTmTxnOrderDetList.stream().filter(item -> ((McTypeEnum.MC_TYPE_MFD.getMcTypeCode().equals(item.getMcType().substring(0, 1))) && mchntNo.equals(item.getMchntNo()))).collect(Collectors.toList());
        if (oriTrialTmTxnOrderDetListMdf.isEmpty()) {
            rglog.error("法人机构<{}> 交易日期<{}> 原交易流水<{}> 商户<{}> 对应的商户手续费优惠回退试算订单明细为0条,继续处理下一条退款明细!",
                    globalInstId, transDate, origTraceNo, mchntNo);
            return;
        }

        /* 如果原试算订单明细超过1条数据,则返回失败 */
        if (CommonConstant.ONE != oriTrialTmTxnOrderDetListMdf.size() || CommonConstant.ONE != oriTmTxnOrderDetListMdf.size()) {
            rglog.error("法人机构<{}> 交易日期<{}> 交易流水<{}> 商户<{}> 对应的商户手续费优惠明细，或手续费优惠回退试算明细多于1条,返回失败,不做处理!",
                    globalInstId, transDate, origTraceNo, mchntNo);
            throw new BizException(RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REFUND_PROCEDURE_FAILED_ERROR.getRespDesc());
        }

        //获取的原商户手续费优惠订单明细
        TMTxnOrderDet oriTmTxnOrderDet = oriTmTxnOrderDetListMdf.get(CommonConstant.ZERO);
        //获取的原商户手续费优惠回退试算订单明细
        TMTxnOrderDet oriTrialTmTxnOrderDet = oriTrialTmTxnOrderDetListMdf.get(CommonConstant.ZERO);

        rglog.error("法人机构<{}> 交易日期<{}> 原交易流水<{}> 商户<{}> 已获取到原交易订单明细及回退试算交易明细，流程继续", globalInstId, transDate, origTraceNo, mchntNo);
        //关联信息
        String relativeDataTrail = oriTrialTmTxnOrderDet.getRelativeData();
        JSONObject relativeDataJsonTrail = JSONObject.parseObject(relativeDataTrail);
        //商户应收手续费金额
        String mchntFeeReceivable = relativeDataJsonTrail.get("mchntFeeReceivable").toString();
        //商户手续费优惠营销活动编号
        String mchntFeeDiscountMcNo = oriTrialTmTxnOrderDet.getMcNo();
        //手续费优惠金额
        String mchntFeeDiscount = oriTrialTmTxnOrderDet.getSubsidy();
        //实收手续费金额
        String mchntFeeActual = new BigDecimal(oriTrialTmTxnOrderDet.getOriginalAmt()).subtract(new BigDecimal(oriTrialTmTxnOrderDet.getSubsidy())).toString();
        //回退试算订单金额
        String orderAmt = relativeDataJsonTrail.get("orderAmt").toString();

        //对返回的请求的订单明细中的字段赋值
        paymentReturnOrderInfoBean.setMchntNo(mchntNo);
        paymentReturnOrderInfoBean.setOrderAmt(orderAmt);
        paymentReturnOrderInfoBean.setMchntSettleAmt(orderAmt);
        paymentReturnOrderInfoBean.setMchntFeeReceivable(mchntFeeReceivable);
        paymentReturnOrderInfoBean.setMchntFeeDiscountMcNo(mchntFeeDiscountMcNo);
        paymentReturnOrderInfoBean.setMchntFeeDiscount(mchntFeeDiscount);
        paymentReturnOrderInfoBean.setMchntFeeActual(mchntFeeActual);

        //查询退货统计表,并登记或更新退货统计表，同时更新手续费优惠回退试算订单明细和手续费优惠订单明细
        TMStatRefundMapper tmStatRefundMapper = new TMStatRefundMapperImpl();
        TMStatRefund tmStatRefund = tmStatRefundMapper.selectSingleRecordFromTMStatRefund(globalInstId, origTxnDate, origTraceNo, mchntNo);
        if (null == tmStatRefund) {
            rglog.info("商户号<{}> 原流水号<{}>未取到退货记录，说明之前未有过退货订单,本次插入一条记录!", mchntNo, origTraceNo);
            //登记退货统计表，更新手续费回退试算订单流水，更新手续费回退试算订单流水明细,判断当前交易是否在原交易日期的统计周期内，如果在需要更新当前交易的单日统计表
            recordTMStatRefund(tmTxnOrder, OriTrialTmTxnOrder, oriTrialTmTxnOrderDet);
        } else {
            rglog.info("商户号<{}> 原流水号<{}>已取到退货记录，说明之前有过退货订单，本次更新记录", mchntNo, origTraceNo);
            //更新手续费回退试算订单流水明细,更新手续费优惠订单流水明细,判断当前交易是否在原交易日期的统计周期内，如果在需要更新当前交易的单日统计表
            updateTMStatRefund(tmTxnOrder, OriTrialTmTxnOrder, oriTrialTmTxnOrderDet, tmStatRefund);
        }

        //更新手续费优惠回退试算订单流水
        rglog.info("商户号<{}> 原流水号<{}> 更新手续费优惠回退试算订单流水...", mchntNo, origTraceNo);
        updateTMTxnOrder(tmTxnOrder, OriTrialTmTxnOrder);


        /* 生成本次退款的的订单明细数据 */
        TMTxnOrderDet tmTxnOrderDet1 = convertRefundTxnOrderDetail(paymentReturnOrderInfoBean, oriTmTxnOrderDet, oriTrialTmTxnOrderDet);
        //如果手续费回退的交易有手续费优惠值，则登记订单明细表，如果没有则不登记
        if (new BigDecimal(mchntFeeDiscount).abs().compareTo(BigDecimal.ZERO) > CommonConstant.ZERO
                || CommonConstant.ONE_COMMON_CONSTANT.equals(tmTxnOrderDet1.getRemark1())) {
            globalTMTxnOrderDetList.add(tmTxnOrderDet1);
        }

    }

    /**
     * 登记退货统计表，更新手续费回退试算订单流水，更新手续费回退试算订单流水明细
     *
     * @return void
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/8/29
     */
    private void recordTMStatRefund(TMTxnOrder oriTMTxnOrder, TMTxnOrder oriTMTxnOrderTrial, TMTxnOrderDet oriTMTxnOrderDetTrial) throws Exception {
        String newTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());

        TMStatRefund tmStatRefund = new TMStatRefund();
        //机构编码
        tmStatRefund.setInstId(oriTMTxnOrderTrial.getInstId());
        //交易日期
        tmStatRefund.setTxnDate(oriTMTxnOrder.getTxnDate());
        //交易时间
        tmStatRefund.setTxnTime(oriTMTxnOrder.getTxnTime());
        //系统流水号
        tmStatRefund.setSysSeqNum(oriTMTxnOrder.getFrontSeqNum());
        //订单号
        tmStatRefund.setOrderId(oriTMTxnOrder.getOrderId());
        //商户编号
        tmStatRefund.setMchntNo(oriTMTxnOrderDetTrial.getMchntNo());
        //订单币种
        tmStatRefund.setOrderCcy("CNY");
        //营销活动类型 20-手续费减免优惠活动
        tmStatRefund.setMcType(McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode());
        //交易状态
        tmStatRefund.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
        //业务状态
//        tmStatRefund.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());

        //关联信息
        String relativeDataTrial = oriTMTxnOrderDetTrial.getRelativeData();
        JSONObject relativeDataJsonTrial = JSONObject.parseObject(relativeDataTrial);
        //商户手续费优惠营销活动编号
        String mchntFeeDiscountMcNo = oriTMTxnOrderDetTrial.getMcNo();
        //手续费优惠金额
        String mchntFeeDiscount = oriTMTxnOrderDetTrial.getSubsidy();
        //实收手续费金额
        String mchntFeeActual = new BigDecimal(oriTMTxnOrderDetTrial.getOriginalAmt()).subtract(new BigDecimal(oriTMTxnOrderDetTrial.getSubsidy())).toString();

        //原手续费优惠交易订单金额
        String origOrderAmt = relativeDataJsonTrial.get("origOrderAmt").toString();
        //原手续费优惠交易手续费金额
        String origMchntFee = relativeDataJsonTrial.get("origMchntFee").toString();

        //应收/应退商户手续费
        tmStatRefund.setMchntFee(origMchntFee);
        //订单金额
        tmStatRefund.setOrderAmt(origOrderAmt);

        //手续费减免类营销活动编号
        tmStatRefund.setMcNo(mchntFeeDiscountMcNo);
        //手续费减免类规则顺序号
        tmStatRefund.setRuleIndex(oriTMTxnOrderDetTrial.getRuleIndex());
        //累计退货次数
        tmStatRefund.setRefundCount(CommonConstant.ONE_COMMON_CONSTANT);
        //累计退货订单金额,手续费优惠回退试算的那笔存储的商户退货清算金额
        tmStatRefund.setRefundOrderAmt(relativeDataJsonTrial.get("orderAmt").toString());
        //累计退货手续费金额
        tmStatRefund.setRefundMchntFee(mchntFeeActual);
        //累计退货优惠金额
        tmStatRefund.setRefundSubsidy(mchntFeeDiscount);
        //累计退货银行优惠金额
        tmStatRefund.setRefundBankSubsidy(mchntFeeDiscount);
        //累计退货商户优惠金额
        tmStatRefund.setRefundMchntSubsidy(CommonConstant.ZERO_AMOUNT);
        //创建人
        tmStatRefund.setOprId(CommonConstant.DEFAULT_OPR_ID);
        //创建时间
        tmStatRefund.setCreateTime(newTimeStamp);
        //最后修改人
        tmStatRefund.setLastOprId("");
        //修改时间
        tmStatRefund.setUpdateTime("");
        // 备用字段1
        tmStatRefund.setRemark1("");
        // 备用字段2
        tmStatRefund.setRemark2("");
        // 备用字段3
        tmStatRefund.setRemark3("");
        // 备用字段4
        tmStatRefund.setRemark4("");
        // 备用字段5
        tmStatRefund.setRemark5("");

        //退货统计表中登记的已退货订单金额和本次退货金额(因为是登记所以原表中无数据)
        String alredayRefundAmtAddThis = tmStatRefund.getRefundOrderAmt();
        //更新手续费回退试算订单流水明细,更新手续费优惠订单流水明细，判断当前交易是否在原交易日期的统计周期内，如果在需要更新当前交易的单日统计表
        updateTMTxnOrderDet(oriTMTxnOrder, oriTMTxnOrderDetTrial, tmStatRefund, alredayRefundAmtAddThis);

        //如果是最后一笔退货，更新退货统计表为已全额退款
        if (isLastDeal) {
            tmStatRefund.setBizStatus(BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode());
        } else {
            tmStatRefund.setBizStatus(BizStatusEnum.PROCESS_PARTIALLY_REFUNDED.getBizStatusCode());
        }

        TMStatRefundMapper tmStatRefundMapper = new TMStatRefundMapperImpl();
        int returnCodeTmTxnOrder = tmStatRefundMapper.insertSingleRecordFromTmStatRefund(tmStatRefund);
        if (CommonConstant.PROCESS_SUCCESS != returnCodeTmTxnOrder) {
            rglog.error("登记退货统计表数据失败! INST_ID=<{}>, TRACE_NO=<{}>, ORDER_ID=<{}>",
                    tmStatRefund.getInstId(), tmStatRefund.getSysSeqNum(), tmStatRefund.getOrderId());
            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
        }

        rglog.info("机构<{}> 商户<{}> 原交易流水<{}> 登记退款统计表成功，流程继续...", tmStatRefund.getInstId(), oriTMTxnOrderDetTrial.getMchntNo(), oriTMTxnOrderDetTrial.getFrontSeqNum());
    }

    /**
     * 更新退货统计表，更新手续费回退试算订单流水明细,更新手续费优惠订单流水明细
     *
     * @return void
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/13
     */
    private void updateTMStatRefund(TMTxnOrder tmTxnOrder, TMTxnOrder tmTxnOrderTrial, TMTxnOrderDet tmTxnOrderDetTrial, TMStatRefund tmStatRefund) throws Exception {
        String newTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());
        //关联信息
        String relativeData = tmTxnOrderDetTrial.getRelativeData();
        JSONObject relativeDataJsonTrail = JSONObject.parseObject(relativeData);
        //原试算订单金额
        String origOrderAmt = relativeDataJsonTrail.get("orderAmt").toString();
        //手续费优惠金额
        String mchntFeeDiscount = tmTxnOrderDetTrial.getSubsidy();
        //实收手续费金额
        String mchntFeeActual = new BigDecimal(tmTxnOrderDetTrial.getOriginalAmt()).subtract(new BigDecimal(tmTxnOrderDetTrial.getSubsidy())).toString();

        TMStatRefund updateTMStatRefund = new TMStatRefund();
        //机构编码
        updateTMStatRefund.setInstId(tmTxnOrderTrial.getInstId());
        //交易日期
        updateTMStatRefund.setTxnDate(tmTxnOrder.getTxnDate());
        //系统流水号
        updateTMStatRefund.setSysSeqNum(tmTxnOrder.getFrontSeqNum());
        //商户编号
        updateTMStatRefund.setMchntNo(tmTxnOrderDetTrial.getMchntNo());
        //累计退货次数
        updateTMStatRefund.setRefundCount(CommonConstant.ONE_COMMON_CONSTANT);
        //累计退货订单金额
        updateTMStatRefund.setRefundOrderAmt(origOrderAmt);
        //累计退货手续费金额
        updateTMStatRefund.setRefundMchntFee(mchntFeeActual);
        //累计退货优惠金额
        updateTMStatRefund.setRefundSubsidy(mchntFeeDiscount);
        //修改时间
        updateTMStatRefund.setUpdateTime(newTimeStamp);
        //订单金额
        updateTMStatRefund.setOrderAmt(tmStatRefund.getOrderAmt());

        //退货统计表中登记的已退货订单金额和本次退货金额
        String alredayRefundAmtAddThis = (new BigDecimal(tmStatRefund.getRefundOrderAmt())).add(new BigDecimal(origOrderAmt)).toString();
        //更新手续费回退试算订单流水明细,更新手续费优惠订单流水明细,判断当前交易是否在原交易日期的统计周期内，如果在需要更新当前交易的单日统计表
        updateTMTxnOrderDet(tmTxnOrder, tmTxnOrderDetTrial, updateTMStatRefund, alredayRefundAmtAddThis);

        //如果是最后一笔退货，更新退货统计表为已全额退款
        if (isLastDeal) {
            updateTMStatRefund.setBizStatus(BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode());
        } else {
            updateTMStatRefund.setBizStatus(BizStatusEnum.PROCESS_PARTIALLY_REFUNDED.getBizStatusCode());
        }

        TMStatRefundMapper tmStatRefundMapper = new TMStatRefundMapperImpl();
        int returnCodeTmTxnOrder = tmStatRefundMapper.updateSingleRecordFromTmStatRefund(updateTMStatRefund);
        if (CommonConstant.PROCESS_SUCCESS != returnCodeTmTxnOrder) {
            rglog.error("更新退货统计表数据失败! INST_ID=<{}>, TRACE_NO=<{}>, ORDER_ID=<{}>",
                    updateTMStatRefund.getInstId(), updateTMStatRefund.getSysSeqNum(), updateTMStatRefund.getOrderId());
            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
        }
    }

    /**
     * 更新手续费优惠回退试算订单明细,更新手续费优惠订单明细，判断当前交易是否在原交易日期的统计周期内，如果在需要更新当前交易的单日统计表
     *
     * @return void
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/8/29
     */
    private void updateTMTxnOrderDet(TMTxnOrder tmTxnOrder, TMTxnOrderDet tmTxnOrderDetTrial, TMStatRefund tmStatRefund, String alredayRefundAmtAddThis) throws Exception {
        String newTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());

        rglog.info("机构<{}> 商户<{}> 原交易流水<{}> 更新回退试算订单明细...", tmStatRefund.getInstId(), tmTxnOrderDetTrial.getMchntNo(), tmTxnOrder.getFrontSeqNum());
        TMTxnOrderDetMapper TmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
        //设置手续费优惠回退试算业务状态为全额退款，对于试算的那笔交易对应的试算流水，只能是全额退款，对应的原交易可能有多条回退试算
        tmTxnOrderDetTrial.setBizStatus(BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode());
        tmTxnOrderDetTrial.setUpdateTime(newTimeStamp);
        //更新手续费回退试算订单流水明细
        int updateTmTxnOrderDetTrialCode = TmTxnOrderDetMapper.updateTmTxnOrderDetByKey(tmTxnOrderDetTrial);
        if (CommonConstant.PROCESS_SUCCESS != updateTmTxnOrderDetTrialCode) {
            rglog.error("更新手续费优惠回退试算订单明细表数据失败! INST_ID=<{}>, TRACE_NO=<{}>, ORDER_ID=<{}>, MCHNT_NO=<{}>",
                    tmTxnOrderDetTrial.getInstId(), tmTxnOrderDetTrial.getFrontSeqNum(), tmTxnOrderDetTrial.getOrderId(), tmTxnOrderDetTrial.getMchntNo());
            throw new BizException(RespCodeEnum.FAILED_UPDATE_T_M_TXN_ORDER_DET.getRespCode(), RespCodeEnum.FAILED_UPDATE_T_M_TXN_ORDER_DET.getRespDesc());
        }

        rglog.info("机构<{}> 商户<{}> 原交易流水<{}> 更新原交易订单明细...", tmStatRefund.getInstId(), tmTxnOrderDetTrial.getMchntNo(), tmTxnOrder.getFrontSeqNum());
        TMTxnOrderDet tmTxnOrderDet = new TMTxnOrderDet();
        //订单明细已经退货订单金额,当没有退货记录时，tmStatRefund传入的是即将登记的实体，当有退货记录是传入的是即将更新的实体
//        BigDecimal alredayRefundAmt = new BigDecimal(tmStatRefund.getRefundOrderAmt());
        //订单明细订单总金额，退货统计表中的订单总金额即为原手续费优惠订单明细金额
        BigDecimal orderAmt = new BigDecimal(tmStatRefund.getOrderAmt());
        //已退款小于订单总金额，如果不小于应该是等于，不可能大于
        if (new BigDecimal(alredayRefundAmtAddThis).compareTo(orderAmt) < 0) {
            //设置手续费优惠业务状态为部分退款
            tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_PARTIALLY_REFUNDED.getBizStatusCode());
            //设置本笔交易不是最后一笔退款
            isLastDeal = false;
        } else {
            //设置手续费优惠业务状态为全额退款
            tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode());
            //设置本笔交易为最后一笔退款
            isLastDeal = true;
        }
        //机构编码
        tmTxnOrderDet.setInstId(tmTxnOrder.getInstId());
        //交易日期
        tmTxnOrderDet.setTxnDate(tmTxnOrder.getTxnDate());
        //前端流水号
        tmTxnOrderDet.setFrontSeqNum(tmTxnOrder.getFrontSeqNum());
        //商户编号
        tmTxnOrderDet.setMchntNo(tmTxnOrderDetTrial.getMchntNo());
        //营销活动编号
        tmTxnOrderDet.setMcNo(tmTxnOrderDetTrial.getMcNo());
        //更新时间
        tmTxnOrderDet.setUpdateTime(newTimeStamp);
        //规则编号
        tmTxnOrderDet.setRuleIndex(tmTxnOrderDetTrial.getRuleIndex());

        //更新原手续费优惠订单明细
        int updateTmTxnOrderDetCode = TmTxnOrderDetMapper.updateTmTxnOrderDetByKey(tmTxnOrderDet);
        if (CommonConstant.PROCESS_SUCCESS != updateTmTxnOrderDetCode) {
            rglog.error("更新手续费优惠订单明细表数据失败! INST_ID=<{}>, TRACE_NO=<{}>, ORDER_ID=<{}>, MCHNT_NO=<{}>",
                    tmTxnOrderDet.getInstId(), tmTxnOrderDet.getFrontSeqNum(), tmTxnOrderDet.getOrderId(), tmTxnOrderDet.getMchntNo());
            throw new BizException(RespCodeEnum.FAILED_UPDATE_T_M_TXN_ORDER_DET.getRespCode(), RespCodeEnum.FAILED_UPDATE_T_M_TXN_ORDER_DET.getRespDesc());
        }

        //判断当前交易是否在原交易日期的统计周期内，如果在需要更新当前交易的单日统计表
        checkDateAndUpdateStatistical(tmTxnOrderDet, tmTxnOrderDetTrial);
    }

    /**
     * 判断是否在支付统计周期内，并更新各单日统计表
     *
     * @param tmTxnOrderDet
     * @throws BizException 异常信息
     * @author liujinan
     * @date 2020/8/29
     */
    private void checkDateAndUpdateStatistical(TMTxnOrderDet tmTxnOrderDet, TMTxnOrderDet tmTxnOrderDetTrial) throws Exception {

        String instId = tmTxnOrderDet.getInstId();
        String mcNo = tmTxnOrderDet.getMcNo();
        String ruleIndex = tmTxnOrderDet.getRuleIndex();
        String txnDate = globalTxnDate;
        String mchntNo = tmTxnOrderDet.getMchntNo();

        MchntInfoMapper mchntInfoMapper = new MchntInfoMapperImpl();
        TBMchntBaseInfo mchntBaseInfo = mchntInfoMapper.selectMompMchntBaseInfoByPrimaryKey(instId, mchntNo);
        if (null == mchntBaseInfo) {
            //查询不到商户信息，流程结束
            rglog.error("查询商户基本信息信息失败, INST_ID=<{}>, MCHNT_NO=<{}>", instId, mchntNo);
            throw new BizException(RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespDesc());
        }
        //商户性质
        String mchntType = mchntBaseInfo.getMchntType();
        //独立营销活动标识
        String idpdCmavyFlg = mchntBaseInfo.getMarketFlag();
        //连锁商户号
        String chainMchntNo = mchntBaseInfo.getChainMchntNo();
        //是否独立维护商户资料
        String independentDataFlag = mchntBaseInfo.getIndependentDataFlag();
        if (CommonConstant.YES.equals(independentDataFlag) && MchntTypeEnum.CHAIN_MCHNT_STORE.getMchntType().equals(mchntType) && CommonConstant.ZERO_COMMON_CONSTANT.equals(idpdCmavyFlg)) {
            rglog.info("商户<{}> 商户类型为11:连锁商户门店，是否独立维护商户资料<{}> 商户独立营销活动标识为<{}>,原正向交易计算营销时根据上级商户<{}> 获取营销活动计算的!", mchntNo, independentDataFlag, idpdCmavyFlg, chainMchntNo);
            mchntNo = chainMchntNo;
        } else {
            rglog.info("商户<{}> 是否独立维护商户资料<{}> 商户类型为<{}> 原正向交易无需判断独立营销活动标识，均使用当前商户号计算的营销！", mchntBaseInfo.getMchntNo(), independentDataFlag, idpdCmavyFlg);
        }

        int limitFlag;

        TMStatMfdCriteriaMapper tmStatMfdCriteriaMapper = new TMStatMfdCriteriaMapperImpl();
        TMStatMfdCriteria tmStatMfdCriteria = tmStatMfdCriteriaMapper.selectTMStatMfdCriteriaByUsingMchntNoAndMcNoAndDateRange(globalInstId, mchntNo, tmTxnOrderDet.getTxnDate(), mcNo);
        if (null == tmStatMfdCriteria) {
            /* 未取到数据,说明当前退货日期已超过原支付交易商户统计周期,不回退额度 */
            rglog.info("当前退货交易日期<{}> 未取到原支付交易在<{}>的流水号<{}>的达标统计表数据,不回退统计周期数据!", globalTxnDate, tmTxnOrderDet.getTxnDate(), tmTxnOrderDet.getFrontSeqNum());
            limitFlag = CommonConstant.FLAG_NOT_SET;
        } else {
            /* 判断当前退货交易日期是否在原支付交易商户统计周期内 */
            if (CommonConstant.ZERO == MompDateUtil.checkDateRange(globalTxnDate, tmStatMfdCriteria.getPeriodStartDate(), tmStatMfdCriteria.getPeriodEndDate())) {
                rglog.info("当前退货交易日期<{}>未超出原支付交易在<{}>的流水号<{}>订单号<{}>的统计周期,继续判断退货时是否到达优惠额度限制!", globalTxnDate, tmTxnOrderDet.getTxnDate(), tmTxnOrderDet.getFrontSeqNum(), tmTxnOrderDet.getOrderId());
                McMchntFeeDiscountTransData mcMchntFeeDiscountTransData = new McMchntFeeDiscountTransData();

                Boolean isReachRuleOrMchntLimit;
                //交易规则为0，则为新商户免手续费的，具体规则号的则为存量商户的
                if (CommonConstant.ZERO_COMMON_CONSTANT.equals(ruleIndex)) {
                    //获取新商户当前各维度统计数据值
                    fetchNewMchntFeeDiscountMcQuotaData(mcMchntFeeDiscountTransData, tmStatMfdCriteria);
                    //判断各维度是否达到上限
                    isReachRuleOrMchntLimit = judgeNewMchntIsReachLimit(mcMchntFeeDiscountTransData, tmStatMfdCriteria);
                } else {
                    //获取当前各维度统计数据值
                    fetchAllMchntFeeDiscountMcQuotaData(mcMchntFeeDiscountTransData, tmStatMfdCriteria);
                    //判断各维度是否达到上限
                    isReachRuleOrMchntLimit = judgeIsReachRuleOrMchntLimit(mcMchntFeeDiscountTransData, tmStatMfdCriteria);
                }
                if (isReachRuleOrMchntLimit) {
                    rglog.info("累计交易额度未达到上限值,需要回退统计周期数据!");
                    limitFlag = CommonConstant.FLAG_SET;
                } else {
                    rglog.info("累计交易额度已达到上限值,不需要回退统计周期数据!");
                    limitFlag = CommonConstant.FLAG_NOT_SET;
                }
            } else {
                rglog.info("当前退货交易日期<{}>已超出原支付交易在<{}>的流水号<{}>的统计周期,不回退统计周期数据!", globalTxnDate, tmTxnOrderDet.getTxnDate(), tmTxnOrderDet.getFrontSeqNum());
                limitFlag = CommonConstant.FLAG_NOT_SET;
            }
        }

        /*当前退货时间在消费交易的统计周期内,需调整额度 */
        if (CommonConstant.FLAG_SET == limitFlag) {
            //关联信息
            String relativeData = tmTxnOrderDetTrial.getRelativeData();
            JSONObject relativeDataJson = JSONObject.parseObject(relativeData);

            //获取回退试算明细中的订单金额（商户清算金额）
            String orderAmtString = relativeDataJson.get("orderAmt").toString();
            BigDecimal orderAmt = new BigDecimal(orderAmtString).multiply(new BigDecimal(CommonConstant.MINUS_ONE)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            //获取回退试算明细中总补贴金额
            BigDecimal totalSubsidyString = new BigDecimal(tmTxnOrderDetTrial.getSubsidy()).multiply(new BigDecimal(CommonConstant.MINUS_ONE)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

            TMStatMfdDay tmStatMfdDay1 = new TMStatMfdDay();
            tmStatMfdDay1.setInstId(instId);
            tmStatMfdDay1.setTxnDate(txnDate);
            tmStatMfdDay1.setMcNo(mcNo);
            tmStatMfdDay1.setRuleIndex(ruleIndex);
            //本笔交易是最后一笔退款，则更新统计表中的累计笔数
            if (isLastDeal) {
                tmStatMfdDay1.setTotalQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
                tmStatMfdDay1.setTxnQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
            } else {
                tmStatMfdDay1.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            tmStatMfdDay1.setTotalAmtAcc(totalSubsidyString.toString());
            tmStatMfdDay1.setTxnAmtAcc(orderAmt.toString());
            tmStatMfdDay1.setMchntQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay1.setMchntOldQualified(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay1.setMchntNewQualified(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay1.setMchntExitQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay1.setAvgAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdDay1.setPaidAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdDay1.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdDay1.setCreateTime(globalTimeStamp);
            tmStatMfdDay1.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdDay1.setUpdateTime(globalTimeStamp);

            rglog.info("机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动单日统计表...", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex());
            /* 手续费减免活动单日统计表 */
            TMStatMfdDayMapper tmStatMfdDayMapper = new TMStatMfdDayMapperImpl();
            int returnCode = tmStatMfdDayMapper.updateMchntFeeDiscountDayStatistics(tmStatMfdDay1);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                if (Database.DBS_NOT_FOUND == returnCode) {
                    int returnCode2 = tmStatMfdDayMapper.insertTMStatMfdDay(tmStatMfdDay1);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                        /* 插入数据失败 */
                        rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                } else {
                    /* 更新数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            }

            //如果当规则不是0 ，则还需要更新规则为0的记录
            if (!CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStatMfdDay1.getRuleIndex())) {
                tmStatMfdDay1.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);

                returnCode = tmStatMfdDayMapper.updateMchntFeeDiscountDayStatistics(tmStatMfdDay1);
                if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                    if (Database.DBS_NOT_FOUND == returnCode) {
                        int returnCode2 = tmStatMfdDayMapper.insertTMStatMfdDay(tmStatMfdDay1);
                        if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                            /* 插入数据失败 */
                            rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex(), returnCode);
                            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                        }
                    } else {
                        /* 更新数据失败 */
                        rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                }
            }

            /* 手续费减免活动商户单日统计表 */
            TMStatMfdMchntDay tmStatMfdMchntDay1 = new TMStatMfdMchntDay();
            tmStatMfdMchntDay1.setInstId(instId);
            tmStatMfdMchntDay1.setTxnDate(globalTxnDate);
            tmStatMfdMchntDay1.setMcNo(mcNo);
            tmStatMfdMchntDay1.setMchntNo(mchntNo);
            tmStatMfdMchntDay1.setRuleIndex(ruleIndex);
            //本笔交易是最后一笔退款，则更新统计表中的累计笔数
            if (isLastDeal) {
                tmStatMfdMchntDay1.setTotalQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
                tmStatMfdMchntDay1.setTxnQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
            } else {
                tmStatMfdMchntDay1.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdMchntDay1.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            tmStatMfdMchntDay1.setTotalAmtAcc(totalSubsidyString.toString());
            tmStatMfdMchntDay1.setTxnAmtAcc(orderAmt.toString());
            tmStatMfdMchntDay1.setTotalAvgAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdMchntDay1.setExitStatus(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay1.setCashbackStatus(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay1.setCashbackAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdMchntDay1.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdMchntDay1.setCreateTime(globalTimeStamp);
            tmStatMfdMchntDay1.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdMchntDay1.setUpdateTime(globalTimeStamp);

            rglog.info("机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表...", tmStatMfdMchntDay1.getInstId(), tmStatMfdMchntDay1.getMcNo(), tmStatMfdMchntDay1.getRuleIndex());
            /* 手续费减免活动商户单日统计表 */
            TMStatMfdMchntDayMapper tmStatMfdMchntDayMapper = new TMStatMfdMchntDayMapperImpl();
            int returnCode2 = tmStatMfdMchntDayMapper.updateMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay1);
            if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                if (Database.DBS_NOT_FOUND == returnCode) {
                    int returnCode3 = tmStatMfdMchntDayMapper.insertMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay1);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode3) {
                        /* 插入数据失败 */
                        rglog.error("插入法人机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表数据失败! RETURN_CODE=<{}>", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                } else {
                    /* 更新数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay1.getInstId(), tmStatMfdMchntDay1.getMcNo(), tmStatMfdMchntDay1.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            }

            //如果当规则不是0 ，则还需要更新规则为0的记录
            if (!CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStatMfdMchntDay1.getRuleIndex())) {
                tmStatMfdMchntDay1.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);

                returnCode2 = tmStatMfdMchntDayMapper.updateMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay1);
                if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                    if (Database.DBS_NOT_FOUND == returnCode) {
                        int returnCode3 = tmStatMfdMchntDayMapper.insertMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay1);
                        if (CommonConstant.PROCESS_SUCCESS != returnCode3) {
                            /* 插入数据失败 */
                            rglog.error("插入法人机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表数据失败! RETURN_CODE=<{}>", tmStatMfdDay1.getInstId(), tmStatMfdDay1.getMcNo(), tmStatMfdDay1.getRuleIndex(), returnCode);
                            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                        }
                    } else {
                        /* 更新数据失败 */
                        rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay1.getInstId(), tmStatMfdMchntDay1.getMcNo(), tmStatMfdMchntDay1.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                }
            }
        }
    }

    /**
     * 更新手续费回退试算订单流水
     *
     * @return void
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/8/29
     */
    private void updateTMTxnOrder(TMTxnOrder tmTxnOrder, TMTxnOrder tmTxnOrderTrial) throws Exception {
        String newTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());

        //手续费优惠回退试算设置业务状态，金额只能为全额
        tmTxnOrderTrial.setBizStatus(BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode());
        tmTxnOrderTrial.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
        tmTxnOrderTrial.setUpdateTime(newTimeStamp);
        //更新手续费优惠回退试算订单流水
        int updateTxnOrderTrialBizStatusReturnCode = updateTxnOrderBizStatusInfo(tmTxnOrderTrial);
        if (CommonConstant.PROCESS_SUCCESS != updateTxnOrderTrialBizStatusReturnCode) {
            rglog.error("更新订单流水表失败,流水号<{}>!", tmTxnOrderTrial.getFrontSeqNum());
            throw new BizException(RespCodeEnum.FAILED_UPDATE_T_M_TXN_ORDER.getRespCode(), RespCodeEnum.FAILED_UPDATE_T_M_TXN_ORDER.getRespDesc());
        }
    }

    /**
     * 更新订单流水表业务状态
     *
     * @param tmTxnOrder
     * @return int
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/8/29
     */
    private int updateTxnOrderBizStatusInfo(TMTxnOrder tmTxnOrder) throws Exception {

        TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();
        int returnCode = tmTxnOrderMapper.updateFeeDiscountOriginalTransactionOrderBizStatus(tmTxnOrder, tmTxnOrder.getBizStatus());
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("商户号<{}> 交易流水号<{}> 更新订单流水表业务状态失败!", tmTxnOrder.getMchntNo(), tmTxnOrder.getFrontSeqNum());
            return CommonConstant.PROCESS_FAILED;
        } else {
            return CommonConstant.PROCESS_SUCCESS;
        }
    }

    /**
     * 使用主键取手续费减免活动单日统计表单条数据
     *
     * @param instId    法人机构号
     * @param mcNo      营销活动编号
     * @param ruleIndex 规则顺序号
     * @param transDate 交易日期
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdDay 手续费减免活动单日统计表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/8/29 15:23
     */
    private TMStatMfdDay selectMchntFeeDiscountDayStatisticsByPK(String instId, String mcNo, String ruleIndex, String transDate) throws Exception {

        TMStatMfdDayMapper tmStatMfdDayMapper = new TMStatMfdDayMapperImpl();
        return tmStatMfdDayMapper.selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, ruleIndex, transDate);
    }

    /**
     * 使用主键取手续费减免活动商户单日统计表单条数据
     *
     * @param instId    法人机构号
     * @param mcNo      营销活动编号
     * @param ruleIndex 规则顺序号
     * @param mchntNo   商户编号
     * @param txnDate   交易日期
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdMchntDay 手续费减免活动商户单日统计表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/8/29 15:23
     */
    private TMStatMfdMchntDay selectMchntFeeDiscountMchntDayStatisticsByPK(String instId, String mcNo, String ruleIndex, String mchntNo, String txnDate) throws Exception {

        TMStatMfdMchntDayMapper tmStatMfdMchntDayMapper = new TMStatMfdMchntDayMapperImpl();
        return tmStatMfdMchntDayMapper.selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, txnDate);
    }

    /**
     * 当前退货订单明细记录数据准备
     *
     * @param tmTxnOrderDet 订单明细表
     * @return cc.rengu.igas.momp.common.entity.TMTxnOrderDet 订单明细表
     * @author liujinan
     * @since 2020/8/29 14:53
     */
    private TMTxnOrderDet convertRefundTxnOrderDetail(PaymentReturnOrderInfoBean paymentReturnOrderInfoBean, TMTxnOrderDet tmTxnOrderDet, TMTxnOrderDet oriTmTxnOrderDet) {

        TMTxnOrderDet tmTxnOrderDet1 = new TMTxnOrderDet();

        /* 手续费优惠订单明细数据准备 */
        tmTxnOrderDet1.setInstId(globalInstId);
        tmTxnOrderDet1.setTxnDate(globalTxnDate);
        tmTxnOrderDet1.setFrontSeqNum(globalTraceNo);
        tmTxnOrderDet1.setOrderId(globalOrderId);
        tmTxnOrderDet1.setMchntNo(tmTxnOrderDet.getMchntNo());
        tmTxnOrderDet1.setUserId(tmTxnOrderDet.getUserId());
        tmTxnOrderDet1.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
        tmTxnOrderDet1.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
        tmTxnOrderDet1.setMcType(tmTxnOrderDet.getMcType());
        tmTxnOrderDet1.setOriginalAmt(new BigDecimal(paymentReturnOrderInfoBean.getMchntFeeReceivable()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
        tmTxnOrderDet1.setMcNo(tmTxnOrderDet.getMcNo());
        tmTxnOrderDet1.setRuleIndex(tmTxnOrderDet.getRuleIndex());
        tmTxnOrderDet1.setSubsidy(paymentReturnOrderInfoBean.getMchntFeeDiscount());
        tmTxnOrderDet1.setBankSubsidy(paymentReturnOrderInfoBean.getMchntFeeDiscount());
        tmTxnOrderDet1.setMchntSubsidy(CommonConstant.ZERO_AMOUNT);
        tmTxnOrderDet1.setRelativeData(oriTmTxnOrderDet.getRelativeData());
        tmTxnOrderDet1.setOrderRemark(oriTmTxnOrderDet.getOrderRemark());
        tmTxnOrderDet1.setOprId(CommonConstant.DEFAULT_OPR_ID);
        tmTxnOrderDet1.setCreateTime(globalTimeStamp);

        //关联信息
        String oriRelativeData = tmTxnOrderDet.getRelativeData();
        JSONObject oriRelativeDataJson = JSONObject.parseObject(oriRelativeData);
        //原手续费优惠交易订单金额
        String origOrderAmt = oriRelativeDataJson.get("orderAmt").toString();
        String disTxAmt = tmTxnOrderDet.getDisTxAmt();
        BigDecimal oriDisTxAmt;
        BigDecimal origOrderAmtBigdecimal = new BigDecimal(origOrderAmt);
        BigDecimal mchntFeeDiscount = new BigDecimal(paymentReturnOrderInfoBean.getMchntFeeDiscount());
        if (null != disTxAmt) {
            oriDisTxAmt = new BigDecimal(disTxAmt);
        } else {
            oriDisTxAmt = origOrderAmtBigdecimal;
        }
        //如果原订单金额和优惠交易金额相同，则 原交易不是商户最后一笔非全额优惠，则本笔优惠交易金额和本笔上送的优惠交易金额相同
        if (oriDisTxAmt.compareTo(origOrderAmtBigdecimal) == 0) {
            //如果当前是最后部分退货的最后一笔退款，或者是全额退款，如果本笔交易有手续费优惠，则
            if (mchntFeeDiscount.compareTo(BigDecimal.ZERO) > 0) {
                tmTxnOrderDet1.setDisTxAmt(paymentReturnOrderInfoBean.getOrderAmt());
            } else {
                //如果没有手续费优惠，则本笔优惠交易金额为0
                tmTxnOrderDet1.setDisTxAmt(CommonConstant.ZERO_AMOUNT);
            }
        } else {
            //如果不相同，则原交易为此商户最后一笔非全金额手续费优惠,只有当最后一笔退款时登记优惠交易金额，其他时候为0
            if (isLastDeal) {
                tmTxnOrderDet1.setDisTxAmt(tmTxnOrderDet.getDisTxAmt());
                //使用remark1标识，此订单虽然没有手续费优惠但是需要登记订单明细（有优惠交易金额）
                tmTxnOrderDet1.setRemark1(CommonConstant.ONE_COMMON_CONSTANT);
            } else {
                tmTxnOrderDet1.setDisTxAmt(CommonConstant.ZERO_AMOUNT);
            }
        }

        return tmTxnOrderDet1;
    }

    /**
     * 判断规则限制是否达到上限
     *
     * @author liujinan
     * @date 2020/9/23 17:27
     */
    private Boolean judgeIsReachRuleOrMchntLimit(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, TMStatMfdCriteria tmStatMfdCriteria) throws Exception {

        String instId = tmStatMfdCriteria.getInstId();
        String mcNo = tmStatMfdCriteria.getMcNo();
        String mchntNo = tmStatMfdCriteria.getMchntNo();

        mcMchntFeeDiscountTransData.setInstId(instId);
        mcMchntFeeDiscountTransData.setMcNo(mcNo);
        mcMchntFeeDiscountTransData.setMchntNo(mchntNo);

        //手续费减免活动商户统计 具体规则-累计优惠交易金额
        BigDecimal txnAmtAcc = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTxnAmtAcc());
        //手续费减免活动商户单日统计数据 具体规则-累计优惠金额
        BigDecimal txnAmtAccDay = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTxnAmtAcc());
        //规则维度判断是否达到上限使用-规则为指定优惠交易金额
        BigDecimal alredayUseedTxnAmtAccRule = txnAmtAcc.add(txnAmtAccDay);
        //规则维度判断是否达到上限使用-规则为指定优惠手续费金额
        BigDecimal alredayUseedTotalAmtAccRule = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTotalAmtAcc()).add(new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTotalAmtAcc()));

        rglog.info("机构<{}>营销活动<{}> 规则<{}> 商户<{}> 开始进行规则层面额度是否达到上限判断...", instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), mchntNo);
        //获取当前规则的上限值
        String ruleLimit;
        if (null != tmStatMfdCriteria.getMrctDisUpLmtVal() && !"".equals(tmStatMfdCriteria.getMrctDisUpLmtVal())) {
            rglog.info("营销活动<{}> 商户<{}> 达标统计表 商户优惠上限值 字段有值，直接使用字段值<{}> 作为上限，无需通过计算规则重新计算!", mcNo, mchntNo, tmStatMfdCriteria.getMrctDisUpLmtVal());
            ruleLimit = tmStatMfdCriteria.getMrctDisUpLmtVal();
        } else {
            /* 根据营销活动规则计算商户当前优惠限额 */
            if (FeeCalTypeEnum.TYPE_0.getRuleType().equals(mcMchntFeeDiscountTransData.getCalRuleNo())) {
                /* 无上限，肯定没有达到额度*/
                rglog.info("机构<{}>营销活动<{}> 规则<{}>的计算规则<{}> 规则设置无优惠上限！",
                        instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), mcMchntFeeDiscountTransData.getCalRuleNo());
                ruleLimit = CommonConstant.BIG_NUMBER;
            } else if (FeeCalTypeEnum.TYPE_1.getRuleType().equals(mcMchntFeeDiscountTransData.getCalRuleNo()) ||
                    FeeCalTypeEnum.TYPE_13.getRuleType().equals(mcMchntFeeDiscountTransData.getCalRuleNo())) {
                /* 无需取优惠限额的计算规则,直接使用规则中的限额 */
                ruleLimit = mcMchntFeeDiscountTransData.getDiscountLimit();
                rglog.info("机构<{}>营销活动<{}> 规则<{}>的计算规则<{}> 规则设置指定具体金额<{}>！",
                        instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), mcMchntFeeDiscountTransData.getCalRuleNo(), ruleLimit);
            } else {
                TMPlatCalRule tmPlatCalRule = selectCalculationRuleInfoByPK(instId, mcMchntFeeDiscountTransData.getCalRuleNo());
                if (null == tmPlatCalRule) {
                    /* 未取到营销活动规则信息,本营销活动不可以优惠! */
                    rglog.info("获取机构<{}>的营销活动<{}>的优惠规则<{}>的计算规则<{}>信息匹配,本营销活动不予优惠!",
                            instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), mcMchntFeeDiscountTransData.getCalRuleNo());
                    throw new BizException(RespCodeEnum.GET_MC_RULE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MC_RULE_INFO_ERROR.getRespDesc());
                }
                //根据规则计算限额值
                ruleLimit = calculateMchntFeeDiscountLimit(instId, mchntNo, tmPlatCalRule.getRuleType(), tmStatMfdCriteria.getCriteriaValue());
                rglog.info("机构<{}>营销活动<{}> 规则<{}>的计算规则<{}> 规则设置上限计算方式<{}>，计算出的值为<{}>！",
                        instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), mcMchntFeeDiscountTransData.getCalRuleNo(), tmPlatCalRule.getRuleType(), ruleLimit);
            }
        }

        if (FeeCalTypeEnum.TYPE_13.getRuleType().equals(mcMchntFeeDiscountTransData.getCalRuleNo())) {
            rglog.info("机构<{}>营销活动<{}> 规则<{}> ,规则限制的为优惠手续费限额!", instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex());
            if (alredayUseedTotalAmtAccRule.compareTo(new BigDecimal(ruleLimit)) >= CommonConstant.ZERO) {
                rglog.info("机构<{}>营销活动<{}> 规则<{}> ，优惠限额<{}> 规则层面已累计使用额度<{}> 规则层面已达到指定优惠手续费限额，退款不再回退额度",
                        instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), ruleLimit, alredayUseedTotalAmtAccRule);
                return false;
            } else {
            }
        } else {
            if (alredayUseedTxnAmtAccRule.compareTo(new BigDecimal(ruleLimit)) >= CommonConstant.ZERO) {
                rglog.info("机构<{}>营销活动<{}> 规则<{}> ，优惠限额<{}> 规则层面已累计使用额度<{}> 规则层面已达到限额，退款不再回退额度",
                        instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), ruleLimit, alredayUseedTxnAmtAccRule);
                return false;
            } else {
            }
        }

        /* 判断单个商户营销活动优惠退出条件 */
        String terminationFlag = mcMchntFeeDiscountTransData.getTerminationFlag();
        //按条件退出
        if (CommonConstant.MCHNT_FEE_EXIT_UNDER_CONDITION.equals(terminationFlag)) {

            /* 单个商户优惠交易笔数上限 */
            BigDecimal quantityLimit = new BigDecimal(mcMchntFeeDiscountTransData.getQuantityLimit());
            /* 单个商户优惠交易金额上限 */
            BigDecimal amountLimit = new BigDecimal(mcMchntFeeDiscountTransData.getAmountLimit());
            if (null != tmStatMfdCriteria.getMrctDisUpLmtVal() && !"".equals(tmStatMfdCriteria.getMrctDisUpLmtVal())) {
                rglog.info("营销活动<{}> 商户<{}> 达标统计表 商户优惠上限值 字段有值，直接使用字段值<{}> 作为上限，无需通过计算规则重新计算!", mcNo, mchntNo, mcMchntFeeDiscountTransData.getMrctDisUpLmtVal());
                amountLimit = new BigDecimal(tmStatMfdCriteria.getMrctDisUpLmtVal());
            } else {
            }
            /* 单个商户手续费优惠额上限 */
            BigDecimal feeLimit = new BigDecimal(mcMchntFeeDiscountTransData.getFeeLimit());

            rglog.info("机构<{}>营销活动<{}> 商户<{}> 开始进行单个商户退出条件层面额度是否达到上限判断...", instId, mcNo, mchntNo);
            //累计优惠笔数
            BigDecimal totalQtyAcc9999 = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTotalQtyAcc9999());
            //累计优惠金额
            BigDecimal totalAmtAcc9999 = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTotalAmtAcc9999());
            //累计交易金额
            BigDecimal txnAmtAcc9999 = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTxnAmtAcc9999());
            //手续费减免活动商户单日统计数据 规则为0-累计优惠笔数
            BigDecimal totalQtyAccDayZero = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTotalQtyAccZero());
            //手续费减免活动商户单日统计数据 规则为0-累计优惠金额
            BigDecimal totalAmtAccDayZero = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTotalAmtAccZero());
            //手续费减免活动商户单日统计数据 规则为0-累计交易金额
            BigDecimal txnAmtAccDayZero = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTxnAmtAccZero());
            //商户维度判断是否达到上限使用
            BigDecimal totalQtyAccMchnt = totalQtyAcc9999.add(totalQtyAccDayZero);
            BigDecimal totalAmtAccMchnt = totalAmtAcc9999.add(totalAmtAccDayZero);
            BigDecimal txnAmtAccMchnt = txnAmtAcc9999.add(txnAmtAccDayZero);

            if (quantityLimit.compareTo(BigDecimal.ZERO) > CommonConstant.ZERO &&
                    totalQtyAccMchnt.compareTo(quantityLimit) >= CommonConstant.ZERO) {
                rglog.info("机构<{}> 营销活动<{}> 单个商户优惠交易笔数上限<{}> 商户已使用额度<{}> 单个商户退出条件已达到限额，退款不再回退额度",
                        instId, mcNo, quantityLimit, totalQtyAccMchnt);
                return false;
            }
            if (feeLimit.compareTo(BigDecimal.ZERO) > CommonConstant.ZERO &&
                    totalAmtAccMchnt.compareTo(feeLimit) >= CommonConstant.ZERO) {
                rglog.info("机构<{}> 营销活动<{}> 单个商户优惠交易手续费上限<{}> 商户已使用额度<{}> 单个商户退出条件已达到限额，退款不再回退额度",
                        instId, mcNo, feeLimit, totalAmtAccMchnt);
                return false;
            }

            if (amountLimit.compareTo(BigDecimal.ZERO) > CommonConstant.ZERO &&
                    txnAmtAccMchnt.compareTo(amountLimit) >= CommonConstant.ZERO) {
                rglog.info("机构<{}> 营销活动<{}> 单个商户优惠交易金额上限<{}> 商户已使用额度<{}> 单个商户退出条件已达到限额，退款不再回退额度",
                        instId, mcNo, amountLimit, txnAmtAccMchnt);
                return false;
            }
        }

        /* 判断活动预算资金是否达到上限 */
        //总预算
        BigDecimal budget = new BigDecimal(mcMchntFeeDiscountTransData.getBudget());
        if (budget.compareTo(BigDecimal.ZERO) > CommonConstant.ZERO) {
            //总预算累计消耗金额
            BigDecimal mcTotalAmtAcc = new BigDecimal(mcMchntFeeDiscountTransData.getMcTotalAmtAcc());
            if (mcTotalAmtAcc.compareTo(budget) >= CommonConstant.ZERO) {
                rglog.info("营销活动<{}>已累计优惠金额<{}> 活动总预算<{}> 达到额度值，不回退额度", mcMchntFeeDiscountTransData.getMcNo(), mcMchntFeeDiscountTransData.getMchntFeeDiscount(), mcMchntFeeDiscountTransData.getBudget());
                return false;
            }
        } else {
            rglog.info("默认预算资金无上限,不判断是否达到预算资金");
        }

        rglog.info("机构<{}>营销活动<{}> 规则<{}> 商户<{}> 各额度均未达到上限，需要回退额度", instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), mchntNo);

        return true;
    }

    /**
     * 存量商户根据活动编号获取手续费减免类营销活动规则信息表
     *
     * @param instId 法人机构号
     * @param mcNo   营销活动编号
     * @return cc.rengu.igas.momp.common.entity.TMMcMchntFeeDiscountRuleInfo 商户手续费减免类营销活动规则信息表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/9/23 18:01
     */
    private List<TMMcMchntFeeDiscountRuleInfo> getMchntFeeDiscountMcRuleInfo(String instId, String mcNo) throws Exception {

        McRuleInfoMapper mcRuleInfoMapper = new McRuleInfoMapperImpl();
        return mcRuleInfoMapper.selectMchntFeeDiscountRuleInfoList(instId, mcNo);
    }

    /**
     * 获取商户手续费营销活动的活动规则对应的计算规则
     *
     * @param instId 法人机构号
     * @param ruleNo 规则编号
     * @return cc.rengu.igas.momp.common.entity.TMPlatCalRule 计算规则码表
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/9/23 17:27
     */
    private TMPlatCalRule selectCalculationRuleInfoByPK(String instId, String ruleNo) throws Exception {

        TMPlatCalRuleMapper tmPlatCalRuleMapper = new TMPlatCalRuleMapperImpl();
        return tmPlatCalRuleMapper.selectCalculationRuleInfoByPrimaryKey(instId, ruleNo);
    }

    /**
     * 根据计算规则计算当前商户手续费优惠限额
     *
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/9/23 17:27
     */
    private String calculateMchntFeeDiscountLimit(String instId, String mchntNo, String ruleType, String nowCriteriaValue) throws Exception {

        String month = DateUtil.getFutureMonDay(CommonConstant.MINUS_ONE).substring(0, 6);
        rglog.debug("INST_ID=<{}>, MCHNT_NO=<{}>, MONTH=<{}>", instId, mchntNo, month);

        //商户上月日均余额直接取达标统计表中的当前统计值
        String mchntDeposit = nowCriteriaValue;

        BigDecimal TWO = new BigDecimal("2");
        BigDecimal HUNDARD_1 = new BigDecimal("125");
        BigDecimal HUNDARD_5 = new BigDecimal("500");
        BigDecimal THOUSAND_30 = new BigDecimal("30000");
        BigDecimal THOUSAND_50 = new BigDecimal("50000");
        BigDecimal THOUSAND_100 = new BigDecimal("100000");

        BigDecimal deposit = new BigDecimal(mchntDeposit).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        BigDecimal tenThousand = new BigDecimal("10000").setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        BigDecimal discountLimit;

        if (null != ruleType) {
            switch (FeeCalTypeEnum.getByValue(ruleType)) {
                case TYPE_2:
                    /* 上月日均存款万位取整+3万 */
                    discountLimit = deposit.divideToIntegralValue(tenThousand).add(THOUSAND_30);
                    break;
                case TYPE_3:
                    /* 上月日均存款*2+3万 */
                    discountLimit = deposit.multiply(TWO).add(THOUSAND_30);
                    break;
                case TYPE_4:
                    /* 上月日均存款万位取整+5万 */
                    discountLimit = deposit.divideToIntegralValue(tenThousand).add(THOUSAND_50);
                    break;
                case TYPE_5:
                    /* 上月日均存款*2+5万 */
                    discountLimit = deposit.multiply(TWO).add(THOUSAND_50);
                    break;
                case TYPE_6:
                    /* 上月日均存款每10万优惠125元 */
                    discountLimit = deposit.divide(THOUSAND_100).multiply(HUNDARD_1);
                    break;
                case TYPE_7:
                    /* 上月日均存款每10万优惠500元 */
                    discountLimit = deposit.divide(THOUSAND_100).multiply(HUNDARD_5);
                    break;
                case TYPE_8:
                    /* 上月日均存款 */
                    discountLimit = deposit;
                    break;
                case TYPE_9:
                    /* 上月日均存款每万元取整*2+3万 */
                    rglog.info("手续费计算规则类型 <{}> 上月日均存款每万元*2+3万", ruleType);
                    discountLimit = deposit.divideToIntegralValue(tenThousand).multiply(TWO).multiply(tenThousand).add(THOUSAND_30);
                    break;
                case TYPE_10:
                    /* 上月日均存款每万元*2+5万 */
                    rglog.info("手续费计算规则类型 <{}> 上月日均存款每万元*2+5万", ruleType);
                    discountLimit = deposit.divideToIntegralValue(tenThousand).multiply(TWO).multiply(tenThousand).add(THOUSAND_50);
                    break;
                case TYPE_11:
                    /* 上月日均存款每十万元*2+3万 */
                    rglog.info("手续费计算规则类型 <{}> 上月日均存款每十万元*2+3万", ruleType);
                    discountLimit = deposit.divideToIntegralValue(THOUSAND_100).multiply(THOUSAND_100).multiply(TWO).add(THOUSAND_30);
                    break;
                case TYPE_12:
                    /* 上月日均存款每十万元*2+5万 */
                    rglog.info("手续费计算规则类型 <{}> 上月日均存款每十万元*2+5万", ruleType);
                    discountLimit = deposit.divideToIntegralValue(THOUSAND_100).multiply(THOUSAND_100).multiply(TWO).add(THOUSAND_50);
                    break;
                default:
                    discountLimit = BigDecimal.ZERO;
            }
            rglog.info("规则层面优惠交易金额上限 DISCOUNT_LIMIT=<{}>", discountLimit.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
            return discountLimit.toString();
        } else {
            return CommonConstant.ZERO_AMOUNT;
        }
    }

    /**
     * 取商户手续费优惠类营销活动各维度统计数据
     *
     * @param mcMchntFeeDiscountTransData
     * @return int 返回码
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/9/25 20:22
     */
    private void fetchAllMchntFeeDiscountMcQuotaData(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, TMStatMfdCriteria tmStatMfdCriteria) throws Exception {

        //规则维度批量处理状态
        int batchStatus = CommonConstant.FLAG_NOT_SET;
        int batchStatus_stat_mfd = CommonConstant.FLAG_NOT_SET;
        String instId = tmStatMfdCriteria.getInstId();
        String mcNo = tmStatMfdCriteria.getMcNo();
        String mchntNo = tmStatMfdCriteria.getMchntNo();
        String periodStartDate = tmStatMfdCriteria.getPeriodStartDate();
        String periodEndDate = tmStatMfdCriteria.getPeriodEndDate();
        String lastDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.MINUS_ONE);
        String lastSecondDate = DateUtil.getBaseDateOffsetDay(lastDate, CommonConstant.MINUS_ONE);
        String mcType = mcMchntFeeDiscountTransData.getMcType();

        /* 商户取营销活动规则信息 */
        List<TMMcMchntFeeDiscountRuleInfo> tmMcMchntFeeDiscountRuleInfoList = getMchntFeeDiscountMcRuleInfo(instId, mcNo);
        if (null == tmMcMchntFeeDiscountRuleInfoList || tmMcMchntFeeDiscountRuleInfoList.isEmpty()) {
            /* 未取到营销活动规则信息! */
            rglog.info("获取机构<{}>的营销活动<{}>营销活动规则信息失败!", instId, mcNo);
            throw new BizException(RespCodeEnum.GET_MC_RULE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MC_RULE_INFO_ERROR.getRespDesc());
        }

        /* 代码判断匹配到了哪条规则上 */
        TMMcMchntFeeDiscountRuleInfo tmMcMchntFeeDiscountRuleInfo;
        BigDecimal criteriaValue = new BigDecimal(tmStatMfdCriteria.getCriteriaValue()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        List<TMMcMchntFeeDiscountRuleInfo> tmMcMchntFeeDiscountRuleInfoList1 = new ArrayList<>();
        for (TMMcMchntFeeDiscountRuleInfo tmMcMchntFeeDiscountRuleInfo1 : tmMcMchntFeeDiscountRuleInfoList) {

            BigDecimal floor = new BigDecimal(tmMcMchntFeeDiscountRuleInfo1.getCriteriaFloor()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            BigDecimal celling = new BigDecimal(tmMcMchntFeeDiscountRuleInfo1.getCriteriaCelling()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

            /* 按照左包右不包原则判断 */
            if (CommonConstant.ZERO <= criteriaValue.compareTo(floor) && CommonConstant.ZERO > criteriaValue.compareTo(celling)) {
                tmMcMchntFeeDiscountRuleInfoList1.add(tmMcMchntFeeDiscountRuleInfo1);
            }
        }

        if (tmMcMchntFeeDiscountRuleInfoList1.isEmpty()) {
            /* 判断是否是因为当前统计指超过最高档规则上限,是的话按照最高档规则进行计算 */
            tmMcMchntFeeDiscountRuleInfo = tmMcMchntFeeDiscountRuleInfoList.stream().max(Comparator.comparing(TMMcMchntFeeDiscountRuleInfo::getRuleIndex)).get();
            BigDecimal celling = new BigDecimal(tmMcMchntFeeDiscountRuleInfo.getCriteriaCelling()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            if (CommonConstant.ZERO >= celling.compareTo(criteriaValue)) {
                rglog.info("当前商户<{}>的达标统计值<{}>超过最高一档规则上限<{}>,按照该档规则计算!", mchntNo, criteriaValue.toString(), celling.toString());
            } else {
                rglog.info("获取机构<{}>的营销活动<{}>优惠规则信息匹配失败,无满足条件的规则!", instId, mcNo);
                throw new BizException(RespCodeEnum.GET_MC_RULE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MC_RULE_INFO_ERROR.getRespDesc());
            }
        } else {
            rglog.info("当前商户<{}>,营销活动<{}>符合的规则条数为<{}>,如果多余一条，则取规则号最大的!", mchntNo, mcNo, tmMcMchntFeeDiscountRuleInfoList1.size());
            if (CommonConstant.ONE != tmMcMchntFeeDiscountRuleInfoList1.size()) {
                /* 超过1条以上规则符合条件 */
                tmMcMchntFeeDiscountRuleInfo = tmMcMchntFeeDiscountRuleInfoList1.stream().max(Comparator.comparing(TMMcMchntFeeDiscountRuleInfo::getRuleIndex)).get();
            } else {
                tmMcMchntFeeDiscountRuleInfo = tmMcMchntFeeDiscountRuleInfoList1.get(CommonConstant.ZERO);
            }
        }
        convertMchntFeeDiscountMcRuleInfo(tmMcMchntFeeDiscountRuleInfo, mcMchntFeeDiscountTransData);
        //退款交易时，所对应的规则号
        String ruleIndex = tmMcMchntFeeDiscountRuleInfo.getRuleIndex();
        //查询营销活动信息
        rglog.info("获取营销活动<{}>基本信息", mcNo);
        TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo = getMchntFeeDiscountMcInfo(instId, mcNo);
        if (null == tmMcMchntFeeDiscountInfo) {
            rglog.error("机构<{}>的商户<{}>未获取到商户手续费优惠营销活动信息!", instId, mchntNo);
            throw new BizException(RespCodeEnum.GET_MONEY_OFF_MC_DETAIL_ERROR.getRespCode(), RespCodeEnum.GET_MONEY_OFF_MC_DETAIL_ERROR.getRespDesc());
        }
        convertMchntFeeDiscountMcInfo(tmMcMchntFeeDiscountInfo, mcMchntFeeDiscountTransData);

        String mcStartDate = tmMcMchntFeeDiscountInfo.getMcStartDate();

        /*------------------------------------------------查询营销活动商户维度汇总数据------------------------------------*/
        /* 查询商户手续费优惠营销活动商户统计表数据  查询具体规则维度的统计数值*/
        TMStatMfdMchnt tmStatMfdMchnt = selectMchntFeeDiscountMchntStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, periodStartDate, periodEndDate);
        if (null == tmStatMfdMchnt) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动商户统计表数据查询失败!", globalInstId, mcNo, ruleIndex);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfdMchnt = new TMStatMfdMchnt();
            tmStatMfdMchnt.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);

        }

        /* 查询商户手续费优惠营销活动商户单日统计表数据 具体规则编号的数据*/
        TMStatMfdMchntDay tmStatMfdMchntDay = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, globalTxnDate);
        if (null == tmStatMfdMchntDay) {
            rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, ruleIndex);
            tmStatMfdMchntDay = new TMStatMfdMchntDay();
            tmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }

        /* 查询商户手续费优惠营销活动商户单日统计表数据  规则为0的数据*/
        TMStatMfdMchntDay tmStatMfdMchntDayRuleZero = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, mchntNo, globalTxnDate);
        if (null == tmStatMfdMchntDayRuleZero) {
            rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDayRuleZero = new TMStatMfdMchntDay();
            tmStatMfdMchntDayRuleZero.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDayRuleZero.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDayRuleZero.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDayRuleZero.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }

        /* 查询商户手续费优惠营销活动商户统计表数据  查询规则为9999的数据，这个统计的是营销活动配置商户退出条件时，统计周期内的所有规则的统计值*/
        TMStatMfdMchnt tmStatMfdMchnt9999 = selectNowPeriodDateTMStatMfdMchnt(instId, mcNo, CommonConstant.RULE_NINE, mchntNo, globalTxnDate);
        if (null == tmStatMfdMchnt9999) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动商户统计表数据查询失败!", globalInstId, mcNo, CommonConstant.RULE_NINE);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfdMchnt9999 = new TMStatMfdMchnt();
            tmStatMfdMchnt9999.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt9999.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt9999.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt9999.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }
        String batchDate;
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        String statPrimaryKey = "FeeMchnt" + instId + "_" + mcNo;
        TMStatBak tmStatBak = selectTMStatBakByStatPrimaryKey(globalInstId, McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode(), statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = mcStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //获取的数据累加到活动统计中
            /* 查询商户手续费优惠营销活动商户单日统计表数据 具体规则编号的数据*/
            TMStatMfdMchntDay newtmStatMfdMchntDay = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, batchDate);
            if (null == newtmStatMfdMchntDay) {
                rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, ruleIndex);
                newtmStatMfdMchntDay = new TMStatMfdMchntDay();
                newtmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            /* 查询商户手续费优惠营销活动商户单日统计表数据  规则为0的数据*/
            TMStatMfdMchntDay newtmStatMfdMchntDayRuleZero = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, mchntNo, batchDate);
            if (null == newtmStatMfdMchntDayRuleZero) {
                rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDayRuleZero = new TMStatMfdMchntDay();
                newtmStatMfdMchntDayRuleZero.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDayRuleZero.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDayRuleZero.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDayRuleZero.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            //将单日统计表的数据累加到周期数据上
            if (DateUtil.compareDate(batchDate, periodStartDate) < 0) {
                rglog.error("获取日期<{}>的单日统计不属于在本统计周期中，不需要累加到商户统计表!", batchDate);
            } else {
                rglog.error("获取日期<{}>的单日统计属于在本统计周期中，需要累加到商户统计表!", batchDate);
                copyMchntStatMfdData(tmStatMfdMchnt, newtmStatMfdMchntDay);
                copyMchntStatMfdData(tmStatMfdMchnt9999, newtmStatMfdMchntDayRuleZero);
            }
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }

        /*------------------------------------------------查询营销活动维度汇总数据------------------------------------*/
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        statPrimaryKey = "Fee" + instId + "_" + mcNo;
        tmStatBak = selectTMStatBakByStatPrimaryKey(instId, McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode(), statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = mcStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        /* 查询商户手续费优惠营销活动统计表数据  规则为0的数据*/
        TMStatMfd tmStatMfd = selectMchntFeeDiscountStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
        if (null == tmStatMfd) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动统计表数据查询失败!", globalInstId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfd = new TMStatMfd();
            tmStatMfd.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);

        }

        /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
        TMStatMfdDay tmStatMfdDay = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, globalTxnDate);
        if (null == tmStatMfdDay) {
            rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay = new TMStatMfdDay();
            tmStatMfdDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }
        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //循环获取单日统计表数据并累加
            /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
            TMStatMfdDay tmStatMfdDay2 = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, batchDate);
            if (null == tmStatMfdDay2) {
                rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2 = new TMStatMfdDay();
                tmStatMfdDay2.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            copyStatMfdData(tmStatMfd, tmStatMfdDay2);
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }


        copyMchntFeeDiscountMchntStatData(tmStatMfdMchnt, mcMchntFeeDiscountTransData);
        copyMchntFeeDiscountMchntDayStatData(tmStatMfdMchntDay, mcMchntFeeDiscountTransData);
        copyMchntFeeDiscountMchntStat9999Data(tmStatMfdMchnt9999, mcMchntFeeDiscountTransData);
        copyMchntFeeDiscountMchntDayZeroStatData(tmStatMfdMchntDayRuleZero, mcMchntFeeDiscountTransData);
        copyMchntFeeDiscountZeroStatData(tmStatMfd, tmStatMfdDay, mcMchntFeeDiscountTransData);
        /*------------------------------------------------查询营销活动周期维度汇总数据------------------------------------*/
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = mcStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        /* 查询商户手续费减免活动周期统计表数据  规则为0的数据*/
        TMStatMfdPeriod tmStatMfdPeriod = selectMchntFeeDiscountPeriodStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, globalTxnDate, globalTxnDate);
        if (null == tmStatMfdPeriod) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费减免活动周期统计表数据查询结果为空!", globalInstId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfdPeriod = new TMStatMfdPeriod();
            tmStatMfdPeriod.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdPeriod.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdPeriod.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdPeriod.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            //获取不到周期统计数据，默认按照自然月度配置周期起始日期
            tmStatMfdPeriod.setPeriodStartDate(MompDateUtil.getSecondDay(Integer.parseInt(globalTxnDate.substring(0, 4)), Integer.parseInt(globalTxnDate.substring(4, 6))));
        } else {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}> 商户手续费减免活动周期统计表数据查询结束!", globalInstId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
        }
        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //循环获取单日统计表数据并累加
            /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
            TMStatMfdDay tmStatMfdDay2 = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, batchDate);
            if (null == tmStatMfdDay2) {
                rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, ruleIndex);
                tmStatMfdDay2 = new TMStatMfdDay();
                tmStatMfdDay2.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            //将单日统计表的数据累加到周期数据上
            if (DateUtil.compareDate(batchDate, tmStatMfdPeriod.getPeriodStartDate()) < 0) {
                rglog.error("获取日期<{}>的单日统计不属于在本统计周期中，需要累加到周期统计表!", batchDate);
            } else {
                rglog.error("获取日期<{}>的单日统计属于在本统计周期中，需要累加到周期统计表!", batchDate);
                copyMchntFeeDiscountMchntStatData(tmStatMfdPeriod, tmStatMfdDay2);
            }
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }
        //将累计优惠手续费金额赋值——周期维度判断使用
        copyMchntFeeDiscountPeriodZeroStatData(tmStatMfdPeriod, tmStatMfdDay, mcMchntFeeDiscountTransData);
    }

    /**
     * 手续费减免活动商户统计数据赋值
     *
     * @param tmStatMfdMchnt              手续费减免活动商户统计表
     * @param mcMchntFeeDiscountTransData 操作对象
     * @author liujinan
     * @since 2020/6/5 11:23
     */
    private void copyMchntFeeDiscountMchntStatData(TMStatMfdMchnt tmStatMfdMchnt, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 手续费减免活动商户统计-累计优惠笔数 */
        mcMchntFeeDiscountTransData.setMchntTotalQtyAcc(tmStatMfdMchnt.getTotalQtyAcc());
        /* 手续费减免活动商户统计-累计优惠金额 */
        mcMchntFeeDiscountTransData.setMchntTotalAmtAcc(tmStatMfdMchnt.getTotalAmtAcc());
        /* 手续费减免活动商户统计-累计交易笔数 */
        mcMchntFeeDiscountTransData.setMchntTxnQtyAcc(tmStatMfdMchnt.getTxnQtyAcc());
        /* 手续费减免活动商户统计-累计交易金额 */
        mcMchntFeeDiscountTransData.setMchntTxnAmtAcc(tmStatMfdMchnt.getTxnAmtAcc());
    }

    /**
     * 手续费减免活动商户单日统计数据赋值
     *
     * @param tmStatMfdMchntDay           手续费减免活动商户单日统计表
     * @param mcMchntFeeDiscountTransData 操作对象
     * @author liujinan
     * @since 2020/6/5 11:22
     */
    private void copyMchntFeeDiscountMchntDayStatData(TMStatMfdMchntDay tmStatMfdMchntDay, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 手续费减免活动商户单日统计数据-累计优惠笔数 */
        mcMchntFeeDiscountTransData.setMchntDayTotalQtyAcc(tmStatMfdMchntDay.getTotalQtyAcc());
        /* 手续费减免活动商户单日统计数据-累计优惠金额 */
        mcMchntFeeDiscountTransData.setMchntDayTotalAmtAcc(tmStatMfdMchntDay.getTotalAmtAcc());
        /* 手续费减免活动商户单日统计数据-累计交易笔数 */
        mcMchntFeeDiscountTransData.setMchntDayTxnQtyAcc(tmStatMfdMchntDay.getTxnQtyAcc());
        /* 手续费减免活动商户单日统计数据-累计交易金额 */
        mcMchntFeeDiscountTransData.setMchntDayTxnAmtAcc(tmStatMfdMchntDay.getTxnAmtAcc());
    }

    /**
     * 手续费减免活动商户统计数据(商户维度)赋值
     *
     * @param tmStatMfdMchnt 手续费减免活动商户统计表
     * @author liujinan
     * @since 2020/9/24 11:23
     */
    private void copyMchntFeeDiscountMchntStat9999Data(TMStatMfdMchnt tmStatMfdMchnt, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 总预算累计优惠笔数 */
        mcMchntFeeDiscountTransData.setMchntTotalQtyAcc9999(tmStatMfdMchnt.getTotalQtyAcc());
        /* 总预算累计优惠金额 */
        mcMchntFeeDiscountTransData.setMchntTotalAmtAcc9999(tmStatMfdMchnt.getTotalAmtAcc());
        /* 总预算累计交易笔数 */
        mcMchntFeeDiscountTransData.setMchntTxnQtyAcc9999(tmStatMfdMchnt.getTxnQtyAcc());
        /* 总预算累计交易金额 */
        mcMchntFeeDiscountTransData.setMchntTxnAmtAcc9999(tmStatMfdMchnt.getTxnAmtAcc());
    }

    /**
     * 手续费减免活动商户单日统计数据赋值 规则为0的统计数据
     *
     * @param tmStatMfdMchntDay           手续费减免活动商户单日统计表
     * @param mcMchntFeeDiscountTransData 操作对象
     * @author liujinan
     * @since 2020/9/25 11:22
     */
    private void copyMchntFeeDiscountMchntDayZeroStatData(TMStatMfdMchntDay tmStatMfdMchntDay, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 手续费减免活动商户单日统计数据-累计优惠笔数 */
        mcMchntFeeDiscountTransData.setMchntDayTotalQtyAccZero(tmStatMfdMchntDay.getTotalQtyAcc());
        /* 手续费减免活动商户单日统计数据-累计优惠金额 */
        mcMchntFeeDiscountTransData.setMchntDayTotalAmtAccZero(tmStatMfdMchntDay.getTotalAmtAcc());
        /* 手续费减免活动商户单日统计数据-累计交易笔数 */
        mcMchntFeeDiscountTransData.setMchntDayTxnQtyAccZero(tmStatMfdMchntDay.getTxnQtyAcc());
        /* 手续费减免活动商户单日统计数据-累计交易金额 */
        mcMchntFeeDiscountTransData.setMchntDayTxnAmtAccZero(tmStatMfdMchntDay.getTxnAmtAcc());
    }

    /**
     * 使用主键取手续费减免活动商户统计表单条数据
     *
     * @param instId
     * @param mcNo
     * @param ruleIndex
     * @param mchntNo
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdMchnt
     * @throws Exception
     * @author liujinan
     * @date 2020/9/15
     */
    private TMStatMfdMchnt selectNowPeriodDateTMStatMfdMchnt(String instId, String mcNo, String ruleIndex, String mchntNo, String txnDate) throws Exception {

        TMStatMfdMchntMapper tmStatMfdMchntMapper = new TMStatMfdMchntMapperImpl();
        return tmStatMfdMchntMapper.selectNowPeriodDateTMStatMfdMchnt(instId, mcNo, ruleIndex, mchntNo, txnDate);
    }

    /**
     * 使用主键取手续费减免活动统计表单条数据
     *
     * @param instId    法人机构编号
     * @param mcNo      营销活动编号
     * @param ruleIndex 规则顺序号
     * @return cc.rengu.igas.momp.common.entity.TMStatMfd 手续费减免活动统计表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/20 22:42
     */
    private TMStatMfd selectMchntFeeDiscountStatisticsByPK(String instId, String mcNo, String ruleIndex) throws Exception {

        TMStatMfdMapper tmStatMfdMapper = new TMStatMfdMapperImpl();
        return tmStatMfdMapper.selectMchntFeeDiscountStatisticsByPK(instId, mcNo, ruleIndex);
    }

    /**
     * 使用主键查询手续费减免活动周期统计表单条数据
     *
     * @param instId          法人机构号
     * @param mcNo            营销活动编号
     * @param ruleIndex       规则顺序号
     * @param periodStartDate 周期起始日期
     * @param periodEndDate   周期结束日期
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdPeriod 手续费减免活动周期统计表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/20 23:38
     */
    private TMStatMfdPeriod selectMchntFeeDiscountPeriodStatisticsByPK(String instId, String mcNo, String ruleIndex, String periodStartDate, String periodEndDate) throws Exception {

        TMStatMfdPeriodMapper tmStatMfdPeriodMapper = new TMStatMfdPeriodMapperImpl();
        return tmStatMfdPeriodMapper.selectMchntFeeDiscountPeriodStatisticsByPK(instId, mcNo, ruleIndex, periodStartDate, periodEndDate);
    }

    /**
     * 使用主键取手续费减免活动商户统计表单条数据
     *
     * @param instId          法人机构号
     * @param mcNo            营销活动编号
     * @param ruleIndex       规则顺序号
     * @param mchntNo         商户编号
     * @param periodStartDate 统计周期起始日期
     * @param periodEndDate   统计周期结束日期
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdMchnt 手续费减免活动商户统计表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/20 23:40
     */
    private TMStatMfdMchnt selectMchntFeeDiscountMchntStatisticsByPK(String instId, String mcNo, String ruleIndex, String mchntNo, String periodStartDate, String periodEndDate) throws Exception {

        TMStatMfdMchntMapper tmStatMfdMchntMapper = new TMStatMfdMchntMapperImpl();
        return tmStatMfdMchntMapper.selectMchntFeeDiscountMchntStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, periodStartDate, periodEndDate);
    }

    /**
     * 使用营销活动商户信息对象获取商户手续费优惠类营销活动基本信息
     *
     * @param instId 法人机构号
     * @param mcNo   营销活动编号
     * @return cc.rengu.igas.momp.common.entity.TMMcMchntFeeDiscountInfo 商户手续费减免类营销活动信息表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/9/25 14:14
     */
    private TMMcMchntFeeDiscountInfo getMchntFeeDiscountMcInfo(String instId, String mcNo) throws Exception {

        McDetailInfoMapper mcDetailInfoMapper = new McDetailInfoMapperImpl();
        return mcDetailInfoMapper.selectMchntFeeDiscountMcDetailInfo(instId, mcNo);
    }

    /**
     * 商户手续费优惠营销活动规则信息转换
     *
     * @param tmMcMchntFeeDiscountRuleInfo 商户手续费减免类营销活动规则信息表
     * @author liujinan
     * @since 2020/4/20 20:47
     */
    private void convertMchntFeeDiscountMcRuleInfo(TMMcMchntFeeDiscountRuleInfo tmMcMchntFeeDiscountRuleInfo, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 顺序号 */
        mcMchntFeeDiscountTransData.setRuleIndex(tmMcMchntFeeDiscountRuleInfo.getRuleIndex());
        /* 控制下限 */
        mcMchntFeeDiscountTransData.setCriteriaFloor(tmMcMchntFeeDiscountRuleInfo.getCriteriaFloor());
        /* 控制上限 */
        mcMchntFeeDiscountTransData.setCriteriaCelling(tmMcMchntFeeDiscountRuleInfo.getCriteriaCelling());
        /* 优惠周期 */
        mcMchntFeeDiscountTransData.setDiscountPeriod(tmMcMchntFeeDiscountRuleInfo.getDiscountPeriod());
        /* 优惠类型 */
        mcMchntFeeDiscountTransData.setDiscountType(tmMcMchntFeeDiscountRuleInfo.getDiscountType());
        /* 优惠力度 */
        mcMchntFeeDiscountTransData.setDiscount(tmMcMchntFeeDiscountRuleInfo.getDiscount());
        /* 计算规则编号 */
        mcMchntFeeDiscountTransData.setCalRuleNo(tmMcMchntFeeDiscountRuleInfo.getCalRuleNo());
        /* 优惠上限 */
        mcMchntFeeDiscountTransData.setDiscountLimit(tmMcMchntFeeDiscountRuleInfo.getDiscountLimit());
    }

    /**
     * 商户手续费优惠营销活动信息转换
     *
     * @param tmMcMchntFeeDiscountInfo 商户手续费减免类营销活动信息表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/9/25 17:14
     */
    private void convertMchntFeeDiscountMcInfo(TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) throws Exception {

        /* 营销活动编号 */
        mcMchntFeeDiscountTransData.setMcNo(tmMcMchntFeeDiscountInfo.getMcNo());
        /* 营销活动名称 */
        mcMchntFeeDiscountTransData.setMcName(tmMcMchntFeeDiscountInfo.getMcName());
        /* 营销活动类型 */
        mcMchntFeeDiscountTransData.setMcType(tmMcMchntFeeDiscountInfo.getMcType());
        /* 营销活动状态 */
        mcMchntFeeDiscountTransData.setMcStatus(tmMcMchntFeeDiscountInfo.getMcStatus());
        /* 活动起始日期 */
        mcMchntFeeDiscountTransData.setMcStartDate(tmMcMchntFeeDiscountInfo.getMcStartDate());
        /* 活动截止日期 */
        mcMchntFeeDiscountTransData.setMcEndDate(tmMcMchntFeeDiscountInfo.getMcEndDate());
        /* 活动结束日期 */
        mcMchntFeeDiscountTransData.setMcActualEndDate(tmMcMchntFeeDiscountInfo.getMcActualEndDate());
        /* 存量商户达标条件 */
        mcMchntFeeDiscountTransData.setStockMchntFlag(tmMcMchntFeeDiscountInfo.getStockMchntFlag());
        /* 存量商户支持类型 */
        mcMchntFeeDiscountTransData.setStockMchntType(tmMcMchntFeeDiscountInfo.getStockMchntType());
        /* 有效交易下限 */
        mcMchntFeeDiscountTransData.setEffectiveLimit(tmMcMchntFeeDiscountInfo.getEffectiveLimit());
        /* 新增商户活动标志 */
        mcMchntFeeDiscountTransData.setNewMchntFlag(tmMcMchntFeeDiscountInfo.getNewMchntFlag());
        /* 新增商户免手续费周期 */
        mcMchntFeeDiscountTransData.setNewMchntPeriod(tmMcMchntFeeDiscountInfo.getNewMchntPeriod());
        /* 新增商户周期顺延标志 */
        mcMchntFeeDiscountTransData.setPostponeFlag(tmMcMchntFeeDiscountInfo.getPostponeFlag());
        /* 达标前手续费优惠规则 */
        mcMchntFeeDiscountTransData.setBeforeFlag(tmMcMchntFeeDiscountInfo.getBeforeFlag());
        /* 达标后手续费优惠规则 */
        mcMchntFeeDiscountTransData.setAfterFlag(tmMcMchntFeeDiscountInfo.getAfterFlag());
        /* 优惠退出标志 */
        mcMchntFeeDiscountTransData.setTerminationFlag(tmMcMchntFeeDiscountInfo.getTerminationFlag());
        /* 统计周期 */
        mcMchntFeeDiscountTransData.setStatPeriod(tmMcMchntFeeDiscountInfo.getStatPeriod());
        /* 单个商户优惠交易笔数上限 */
        mcMchntFeeDiscountTransData.setQuantityLimit(tmMcMchntFeeDiscountInfo.getQuantityLimit());
        /* 单个商户优惠交易金额上限 */
        mcMchntFeeDiscountTransData.setAmountLimit(tmMcMchntFeeDiscountInfo.getAmountLimit());
        /* 单个商户手续费优惠额上限 */
        mcMchntFeeDiscountTransData.setFeeLimit(tmMcMchntFeeDiscountInfo.getFeeLimit());
        /* 新商户优惠额上限 */
        mcMchntFeeDiscountTransData.setNewMchntAmountLimit(tmMcMchntFeeDiscountInfo.getNewMchntAmountLimit());
        /* 营销活动预算 */
        mcMchntFeeDiscountTransData.setBudget(tmMcMchntFeeDiscountInfo.getBudget());
        /* 新增商户免费额度类型 */
        mcMchntFeeDiscountTransData.setNewmrctFreeLmtTyp(tmMcMchntFeeDiscountInfo.getNewmrctFreeLmtTyp());
    }

    /**
     * 登记退货统计表 全额退货时使用
     *
     * @return void
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/10/13
     */
    private void recordTMStatRefundFullyNoTrail(TMTxnOrder tmTxnOrder, TMTxnOrderDet tmTxnOrderDet, PaymentReturnOrderInfoBean paymentReturnOrderInfoBean) throws Exception {

        JsonMfdMcOrderRemark jsonMfdMcOrderRemark = JsonOperation.parseMfdMcOrderDetailOrderRemark(tmTxnOrderDet.getOrderRemark(), rglog);

        /* 商户订单金额 */
        BigDecimal origOrderAmt = new BigDecimal(jsonMfdMcOrderRemark.getOrderAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        /* 商户应收手续费 */
        BigDecimal origMchntFeeReceivable = new BigDecimal(jsonMfdMcOrderRemark.getMchntFeeReceivable()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        /* 本笔交易订单金额  取mchntsettle字段的金额值*/
        BigDecimal thisOrderAmt = new BigDecimal(paymentReturnOrderInfoBean.getMchntSettleAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        TMStatRefund tmStatRefund1 = new TMStatRefund();
        tmStatRefund1.setInstId(globalInstId);
        tmStatRefund1.setTxnDate(tmTxnOrder.getTxnDate());
        tmStatRefund1.setTxnTime(tmTxnOrder.getTxnTime());
        tmStatRefund1.setSysSeqNum(tmTxnOrder.getFrontSeqNum());
        tmStatRefund1.setOrderId(tmTxnOrder.getOrderId());
        tmStatRefund1.setMchntNo(tmTxnOrderDet.getMchntNo());
        tmStatRefund1.setOrderCcy("CNY");
        tmStatRefund1.setMcType(tmTxnOrderDet.getMcType());
        tmStatRefund1.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        tmStatRefund1.setOrderAmt(origOrderAmt.toString());
        tmStatRefund1.setMchntFee(origMchntFeeReceivable.toString());
        tmStatRefund1.setMcNo(tmTxnOrderDet.getMcNo());
        tmStatRefund1.setRuleIndex(tmTxnOrderDet.getRuleIndex());
        tmStatRefund1.setRefundCount(CommonConstant.ONE_COMMON_CONSTANT);
        tmStatRefund1.setRefundOrderAmt(thisOrderAmt.toString());
        tmStatRefund1.setRefundMchntFee(new BigDecimal(tmTxnOrderDet.getOriginalAmt()).subtract(new BigDecimal(tmTxnOrderDet.getSubsidy())).toString());
        tmStatRefund1.setRefundSubsidy(tmTxnOrderDet.getSubsidy());
        tmStatRefund1.setRefundBankSubsidy(tmTxnOrderDet.getBankSubsidy());
        tmStatRefund1.setRefundMchntSubsidy(CommonConstant.ZERO_AMOUNT);
        tmStatRefund1.setOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStatRefund1.setCreateTime(globalTimeStamp);
        tmStatRefund1.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStatRefund1.setUpdateTime(globalTimeStamp);
        //全额退款时登记   业务状态
        tmStatRefund1.setBizStatus(BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode());

        TMStatRefundMapper tmStatRefundMapper = new TMStatRefundMapperImpl();
        int returnCodeTmTxnOrder = tmStatRefundMapper.insertSingleRecordFromTmStatRefund(tmStatRefund1);
        if (cc.rengu.jradp.mods.dbs.Database.DBS_SUCCESS != returnCodeTmTxnOrder) {
            rglog.error("登记退货统计表数据失败! INST_ID=<{}>, TRACE_NO=<{}>, ORDER_ID=<{}>",
                    tmStatRefund1.getInstId(), tmStatRefund1.getSysSeqNum(), tmStatRefund1.getOrderId());
            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
        }
    }

    /**
     * 取商户手续费优惠类营销活动各维度统计数据
     *
     * @param mcMchntFeeDiscountTransData
     * @return int 返回码
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/10/20 20:22
     */
    private void fetchNewMchntFeeDiscountMcQuotaData(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, TMStatMfdCriteria tmStatMfdCriteria) throws Exception {

        //规则维度批量处理状态
        int batchStatus_stat_mfd = CommonConstant.FLAG_NOT_SET;
        int batchStatus_stat_mfd_mchnt = CommonConstant.FLAG_NOT_SET;
        String instId = tmStatMfdCriteria.getInstId();
        String mcNo = tmStatMfdCriteria.getMcNo();
        String mchntNo = tmStatMfdCriteria.getMchntNo();
        String periodStartDate = tmStatMfdCriteria.getPeriodStartDate();
        String periodEndDate = tmStatMfdCriteria.getPeriodEndDate();
        String lastDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.MINUS_ONE);
        String lastSecondDate = DateUtil.getBaseDateOffsetDay(lastDate, CommonConstant.MINUS_ONE);
        String ruleIndex = CommonConstant.ZERO_COMMON_CONSTANT;
        String mfdCriteriaCreateTimeTmp = tmStatMfdCriteria.getCreateTime();
        String mfdCriteriaCreateTime = mfdCriteriaCreateTimeTmp.substring(0, 4) + mfdCriteriaCreateTimeTmp.substring(5, 7) + mfdCriteriaCreateTimeTmp.substring(8, 10);

        rglog.info("获取营销活动<{}>基本信息", mcNo);
        TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo = getMchntFeeDiscountMcInfo(instId, mcNo);
        if (null == tmMcMchntFeeDiscountInfo) {
            rglog.error("机构<{}>的商户<{}>未获取到商户手续费优惠营销活动信息!", instId, mchntNo);
            throw new BizException(RespCodeEnum.GET_MONEY_OFF_MC_DETAIL_ERROR.getRespCode(), RespCodeEnum.GET_MONEY_OFF_MC_DETAIL_ERROR.getRespDesc());
        }
        convertMchntFeeDiscountMcInfo(tmMcMchntFeeDiscountInfo, mcMchntFeeDiscountTransData);

        String mcStartDate = tmMcMchntFeeDiscountInfo.getMcStartDate();
        String mcType = tmMcMchntFeeDiscountInfo.getMcType();
        /*------------------------------------------------查询营销活动商户维度汇总数据------------------------------------*/
        /* 查询商户手续费优惠营销活动商户统计表数据  查询具体规则维度的统计数值 新增商户的这个值应该为0*/
        TMStatMfdMchnt tmStatMfdMchnt = selectMchntFeeDiscountMchntStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, periodStartDate, periodEndDate);
        if (null == tmStatMfdMchnt) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动商户统计表数据查询失败!", globalInstId, mcNo, ruleIndex);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfdMchnt = new TMStatMfdMchnt();
            tmStatMfdMchnt.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }

        /* 查询商户手续费优惠营销活动商户单日统计表数据 具体规则编号的数据 新增商户的这个值应该为0*/
        TMStatMfdMchntDay tmStatMfdMchntDay = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, globalTxnDate);
        if (null == tmStatMfdMchntDay) {
            rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, ruleIndex);
            tmStatMfdMchntDay = new TMStatMfdMchntDay();
            tmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }
        String batchDate;
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        String statPrimaryKey = "FeeMchnt" + instId + "_" + mcNo;
        TMStatBak tmStatBak = selectTMStatBakByStatPrimaryKey(globalInstId, mcType, statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = periodStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //获取的数据累加到活动统计中
            /* 查询商户手续费优惠营销活动商户单日统计表数据 具体规则编号的数据*/
            TMStatMfdMchntDay newtmStatMfdMchntDay = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, batchDate);
            if (null == newtmStatMfdMchntDay) {
                rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, ruleIndex);
                newtmStatMfdMchntDay = new TMStatMfdMchntDay();
                newtmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            //将单日统计表的数据累加到周期数据上
            if (DateUtil.compareDate(batchDate, periodStartDate) < 0) {
                rglog.error("获取日期<{}>的单日统计不属于在本统计周期中，不需要累加到商户统计表!", batchDate);
            } else {
                rglog.error("获取日期<{}>的单日统计属于在本统计周期中，需要累加到商户统计表!", batchDate);
                copyMchntStatMfdData(tmStatMfdMchnt, newtmStatMfdMchntDay);
            }
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }

        copyMchntFeeDiscountMchntStatData(tmStatMfdMchnt, mcMchntFeeDiscountTransData);
        copyMchntFeeDiscountMchntDayStatData(tmStatMfdMchntDay, mcMchntFeeDiscountTransData);

        /*------------------------------------------------查询营销活动维度汇总数据------------------------------------*/
        /* 查询商户手续费优惠营销活动统计表数据  规则为0的数据*/
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        statPrimaryKey = "Fee" + instId + "_" + mcNo;
        tmStatBak = selectTMStatBakByStatPrimaryKey(instId, McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode(), statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = mcStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }

        /* 查询商户手续费优惠营销活动统计表数据  规则为0的数据*/
        TMStatMfd tmStatMfd = selectMchntFeeDiscountStatisticsByPK(instId, mcNo, ruleIndex);
        if (null == tmStatMfd) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动统计表数据查询失败!", globalInstId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfd = new TMStatMfd();
            tmStatMfd.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);

        }
        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //循环获取单日统计表数据并累加
            /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
            TMStatMfdDay tmStatMfdDay1 = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, ruleIndex, batchDate);
            if (null == tmStatMfdDay1) {
                rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, ruleIndex);
                tmStatMfdDay1 = new TMStatMfdDay();
                tmStatMfdDay1.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            copyStatMfdData(tmStatMfd, tmStatMfdDay1);
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }

        /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
        TMStatMfdDay tmStatMfdDay = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, ruleIndex, globalTxnDate);
        if (null == tmStatMfdDay) {
            rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, ruleIndex);
            tmStatMfdDay = new TMStatMfdDay();
            tmStatMfdDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }


        //将累计优惠手续费金额赋值
        copyMchntFeeDiscountZeroStatData(tmStatMfd, tmStatMfdDay, mcMchntFeeDiscountTransData);
    }

    /**
     * 手续费减免活动统计数据赋值 规则为0的统计数据
     *
     * @param tmStatMfd    手续费减免活动统计表
     * @param tmStatMfdDay 手续费减免活动单日统计表
     * @author liujinan
     * @since 2020/10/20 11:22
     */
    private void copyMchntFeeDiscountZeroStatData(TMStatMfd tmStatMfd, TMStatMfdDay tmStatMfdDay, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {
        /* 手续费减免活动统计数据-总预算消耗金额 */
        mcMchntFeeDiscountTransData.setMcTotalAmtAcc(new BigDecimal(tmStatMfd.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTotalAmtAcc())).toString());
    }

    /**
     * 判断新商户是否达到额度限制
     *
     * @author liujinan
     * @date 2020/10/20 17:27
     */
    private Boolean judgeNewMchntIsReachLimit(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, TMStatMfdCriteria tmStatMfdCriteria) throws Exception {

        String instId = tmStatMfdCriteria.getInstId();
        String mcNo = tmStatMfdCriteria.getMcNo();
        String mchntNo = tmStatMfdCriteria.getMchntNo();
        String newmrctFreeLmtTyp = mcMchntFeeDiscountTransData.getNewmrctFreeLmtTyp();

        //手续费减免活动商户统计 具体规则-累计优惠交易金额
        BigDecimal txnAmtAcc = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTxnAmtAcc());
        //手续费减免活动商户单日统计数据 具体规则-累计优惠金额
        BigDecimal txnAmtAccDay = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTxnAmtAcc());
        //手续费减免活动商户统计-累计优惠手续费金额
        BigDecimal mchntTotalAmtAcc = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTotalAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        //手续费减免活动商户单日统计数据 具体规则-累计优惠手续费金额
        BigDecimal mchntTotalAmtAccDay = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTotalAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        if (null != tmStatMfdCriteria.getMrctDisUpLmtVal() && !"".equals(tmStatMfdCriteria.getMrctDisUpLmtVal())) {
            rglog.info("营销活动<{}> 商户<{}> 达标统计表 商户优惠上限值 字段有值，直接使用字段值<{}> 作为上限，无需通过计算规则重新计算!", mcNo, mchntNo, tmStatMfdCriteria.getMrctDisUpLmtVal());
            mcMchntFeeDiscountTransData.setNewMchntAmountLimit(tmStatMfdCriteria.getMrctDisUpLmtVal());
        } else {
        }
        /* 判断新商户优惠上限是否超限 */
        BigDecimal discountLimit = new BigDecimal(mcMchntFeeDiscountTransData.getNewMchntAmountLimit()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        //如果新商户上限为免交易金额，为空时默认为免交易金额
        if (null == newmrctFreeLmtTyp || CommonConstant.ZERO_COMMON_CONSTANT.equals(newmrctFreeLmtTyp)) {
            //周期统计累计优惠交易金额 + 单日统计累计优惠交易金额
            BigDecimal totalDiscount = txnAmtAcc.add(txnAmtAccDay).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            rglog.info("新商户周期内优惠上限<{}>,目前已优惠金额<{}>", discountLimit, totalDiscount);

            if (totalDiscount.compareTo(discountLimit) >= CommonConstant.ZERO) {
                /*超过限额，不需要回退额度，*/
                rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}> 新商户优惠交易额上限<{}> ，目前已优惠交易额<{}>，已超限额,不需要回退额度！", instId, mcNo, discountLimit, totalDiscount);
                return false;
            } else {
                /*未超过限额，需要回退额度，*/
                rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}> 新商户优惠交易额上限<{}> ，目前已优惠交易额<{}>，未超限额,判断流程继续！", instId, mcNo, discountLimit, totalDiscount);
            }
        } else {
            //如果新商户上限为免手续费金额
            //周期统计累计优惠交易金额 + 单日统计累计优惠交易金额
            BigDecimal totalMchntFeeDiscount = mchntTotalAmtAcc.add(mchntTotalAmtAccDay).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            rglog.info("新商户周期内优惠上限<{}>,目前已优惠手续费金额<{}>", discountLimit, totalMchntFeeDiscount);

            if (totalMchntFeeDiscount.compareTo(discountLimit) >= CommonConstant.ZERO) {
                /*超过限额，不需要回退额度，*/
                rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}> 新商户优惠手续费上限<{}> ，目前已优惠手续费<{}>，已超限额,不需要回退额度！", instId, mcNo, discountLimit, totalMchntFeeDiscount);
                return false;
            } else {
                /*未超过限额，需要回退额度，*/
                rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}> 新商户优惠手续费上限<{}> ，目前已优惠手续费<{}>，未超限额,判断流程继续！", instId, mcNo, discountLimit, totalMchntFeeDiscount);
            }
        }

        /* 判断活动预算资金是否达到上限 */
        //总预算
        BigDecimal budget = new BigDecimal(mcMchntFeeDiscountTransData.getBudget());
        if (budget.compareTo(BigDecimal.ZERO) > CommonConstant.ZERO) {
            //总预算累计消耗金额
            BigDecimal mcTotalAmtAcc = new BigDecimal(mcMchntFeeDiscountTransData.getMcTotalAmtAcc());
            if (mcTotalAmtAcc.compareTo(budget) >= CommonConstant.ZERO) {
                rglog.info("营销活动<{}>已累计优惠金额<{}> 活动总预算<{}> 达到额度值，不回退额度", mcMchntFeeDiscountTransData.getMcNo(), mcMchntFeeDiscountTransData.getMchntFeeDiscount(), mcMchntFeeDiscountTransData.getBudget());
                return false;
            }
        } else {
            rglog.info("默认预算资金无上限,不判断是否达到预算资金");
        }

        rglog.info("机构<{}>营销活动<{}> 规则<{}> 商户<{}> 各额度均未达到上限，需要回退额度", instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), mchntNo);
        return true;
    }

    /**
     * 检查 上送 订单明细表 金额字段不能为负数
     *
     * @param comboPaymentRefundRequest
     * @author ls
     * @date 2020/10/21
     */
    private void checkTmTxnOrderDetFieldHasNegativeNumber(ComboPaymentRefundRequest comboPaymentRefundRequest) {
        if (comboPaymentRefundRequest.getReturnOrderDetailList().size() > 0) {
            for (PaymentReturnOrderInfoBean paymentReturnOrderInfoBean : comboPaymentRefundRequest.getReturnOrderDetailList()) {
                /*退货订单金额*/
                if (!StringUtil.isNullorEmpty(paymentReturnOrderInfoBean.getOrderAmt()) && new BigDecimal(paymentReturnOrderInfoBean.getOrderAmt()).compareTo(zero) < 0) {
                    throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
                }
                /*商户退货清算金额*/
                if (!StringUtil.isNullorEmpty(paymentReturnOrderInfoBean.getMchntSettleAmt()) && new BigDecimal(paymentReturnOrderInfoBean.getMchntSettleAmt()).compareTo(zero) < 0) {
                    throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
                }
                /*退货商户应收手续费金额*/
                if (!StringUtil.isNullorEmpty(paymentReturnOrderInfoBean.getMchntFeeReceivable()) && new BigDecimal(paymentReturnOrderInfoBean.getMchntFeeReceivable()).compareTo(zero) < 0) {
                    throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
                }
                /*满减实际支付金额*/
                if (!StringUtil.isNullorEmpty(paymentReturnOrderInfoBean.getMoneyOffTxnAmt()) && new BigDecimal(paymentReturnOrderInfoBean.getMoneyOffTxnAmt()).compareTo(zero) < 0) {
                    throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
                }
                /*满减补贴金额*/
                if (!StringUtil.isNullorEmpty(paymentReturnOrderInfoBean.getMoneyOffSubsidyTotal()) && new BigDecimal(paymentReturnOrderInfoBean.getMoneyOffSubsidyTotal()).compareTo(zero) < 0) {
                    throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
                }
                /*满减机构补贴金额 moneyOffSubsidyBank*/
                if (!StringUtil.isNullorEmpty(paymentReturnOrderInfoBean.getMoneyOffSubsidyBank()) && new BigDecimal(paymentReturnOrderInfoBean.getMoneyOffSubsidyBank()).compareTo(zero) < 0) {
                    throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
                }
                /*满减商户补贴金额 moneyOffSubsidyMchnt*/
                if (!StringUtil.isNullorEmpty(paymentReturnOrderInfoBean.getMoneyOffSubsidyMchnt()) && new BigDecimal(paymentReturnOrderInfoBean.getMoneyOffSubsidyMchnt()).compareTo(zero) < 0) {
                    throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
                }
                /*手续费优惠金额 mchntFeeDiscount*/
                if (!StringUtil.isNullorEmpty(paymentReturnOrderInfoBean.getMchntFeeDiscount()) && new BigDecimal(paymentReturnOrderInfoBean.getMchntFeeDiscount()).compareTo(zero) < 0) {
                    throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
                }
                /*实收手续费金额 mchntFeeActual*/
                if (!StringUtil.isNullorEmpty(paymentReturnOrderInfoBean.getMchntFeeActual()) && new BigDecimal(paymentReturnOrderInfoBean.getMchntFeeActual()).compareTo(zero) < 0) {
                    throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
                }
                /*卡券面额 couponDenomination*/
                if (!StringUtil.isNullorEmpty(paymentReturnOrderInfoBean.getCouponDenomination()) && new BigDecimal(paymentReturnOrderInfoBean.getCouponDenomination()).compareTo(zero) < 0) {
                    throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
                }
                /*卡券购买金额 couponPurchaseAmt*/
                if (!StringUtil.isNullorEmpty(paymentReturnOrderInfoBean.getCouponPurchaseAmt()) && new BigDecimal(paymentReturnOrderInfoBean.getCouponPurchaseAmt()).compareTo(zero) < 0) {
                    throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
                }
                /*卡券抵扣补贴金额 couponTotalSubsidy*/
                if (!StringUtil.isNullorEmpty(paymentReturnOrderInfoBean.getCouponTotalSubsidy()) && new BigDecimal(paymentReturnOrderInfoBean.getCouponTotalSubsidy()).compareTo(zero) < 0) {
                    throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
                }
                /*卡券机构补贴金额 couponBankSubsidy*/
                if (!StringUtil.isNullorEmpty(paymentReturnOrderInfoBean.getCouponBankSubsidy()) && new BigDecimal(paymentReturnOrderInfoBean.getCouponBankSubsidy()).compareTo(zero) < 0) {
                    throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
                }
                /*卡券商户补贴金额 couponMchntSubsidy*/
                if (!StringUtil.isNullorEmpty(paymentReturnOrderInfoBean.getCouponMchntSubsidy()) && new BigDecimal(paymentReturnOrderInfoBean.getCouponMchntSubsidy()).compareTo(zero) < 0) {
                    throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
                }
            }
        }
    }

    /**
     * 使用主键查询统计信息备份表最新一条数据
     *
     * @param instId
     * @param statType
     * @param statPrimaryKey
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdPeriod
     * @throws Exception
     * @author liujinan
     * @date 2021/7/9
     */
    private TMStatBak selectTMStatBakByStatPrimaryKey(String instId, String statType, String statPrimaryKey) throws Exception {

        TMStatBakMapper tmStatBakMapper = new TMStatBakMapperImpl();
        return tmStatBakMapper.selectTMStatBakByStatPrimaryKey(instId, statType, statPrimaryKey);
    }

    /**
     * 手续费减免活动周期统计数据赋值
     *
     * @param tmStatMfdPeriod 手续费减免活动周期统计表
     * @param tmStatMfdDay    手续费减免活动单日统计表
     * @author liujinan
     * @since 2021/7/12 11:23
     */
    private void copyMchntFeeDiscountMchntStatData(TMStatMfdPeriod tmStatMfdPeriod, TMStatMfdDay tmStatMfdDay) {

        /* 手续费减免活动周期统计表-累计优惠笔数 */
        tmStatMfdPeriod.setTotalQtyAcc(new BigDecimal(tmStatMfdPeriod.getTotalQtyAcc()).add(new BigDecimal(tmStatMfdDay.getTotalQtyAcc())).toString());
        /* 手续费减免活动周期统计表-累计优惠金额 */
        tmStatMfdPeriod.setTotalAmtAcc(new BigDecimal(tmStatMfdPeriod.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTotalAmtAcc())).toString());
        /* 手续费减免活动周期统计表-累计交易笔数 */
        tmStatMfdPeriod.setTxnQtyAcc(new BigDecimal(tmStatMfdPeriod.getTxnQtyAcc()).add(new BigDecimal(tmStatMfdDay.getTxnQtyAcc())).toString());
        /* 手续费减免活动周期统计表-累计交易金额 */
        tmStatMfdPeriod.setTxnAmtAcc(new BigDecimal(tmStatMfdPeriod.getTxnAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTxnAmtAcc())).toString());
    }

    /**
     * 手续费减免活动周期统计数据赋值 规则为0的统计数据
     *
     * @param tmStatMfdPeriod 手续费减免活动周期统计表
     * @param tmStatMfdDay    手续费减免活动周期统计表
     * @author liujinan
     * @since 2021/7/21 11:22
     */
    private void copyMchntFeeDiscountPeriodZeroStatData(TMStatMfdPeriod tmStatMfdPeriod, TMStatMfdDay tmStatMfdDay, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {
        /* 手续费减免活动周期统计数据-周期内消耗金额+单日消耗金额*/
        mcMchntFeeDiscountTransData.setPeriodTotalAmtAcc(new BigDecimal(tmStatMfdPeriod.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTotalAmtAcc())).toString());
    }

    /**
     * 手续费减免活动商户统计数据赋值
     *
     * @param tmStatMfdMchnt    手续费减免活动商户统计表
     * @param tmStatMfdMchntDay 手续费减免活动商户单日统计表
     * @author Jinan Liu
     * @since 2020/6/5 11:23
     */
    private void copyMchntStatMfdData(TMStatMfdMchnt tmStatMfdMchnt, TMStatMfdMchntDay tmStatMfdMchntDay) {

        /* 营销活动单日累计-总预算累计消耗笔数 */
        tmStatMfdMchnt.setTotalQtyAcc(new BigDecimal(tmStatMfdMchnt.getTotalQtyAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTotalQtyAcc())).toString());
        /* 营销活动单日累计-总预算累计消耗金额 */
        tmStatMfdMchnt.setTotalAmtAcc(new BigDecimal(tmStatMfdMchnt.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTotalAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
        /* 营销活动单日累计-总预算累计消耗笔数 */
        tmStatMfdMchnt.setTxnQtyAcc(new BigDecimal(tmStatMfdMchnt.getTxnQtyAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTxnQtyAcc())).toString());
        /* 营销活动单日累计-总预算累计消耗金额 */
        tmStatMfdMchnt.setTxnAmtAcc(new BigDecimal(tmStatMfdMchnt.getTxnAmtAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTxnAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
    }

    /**
     * 手续费减免活动统计数据赋值
     *
     * @param tmStatMfd    手续费减免活动统计表
     * @param tmStatMfdDay 手续费减免活动单日统计表
     * @author Jinan Liu
     * @since 2020/6/5 11:23
     */
    private void copyStatMfdData(TMStatMfd tmStatMfd, TMStatMfdDay tmStatMfdDay) {

        /* 营销活动单日累计-总预算累计消耗笔数 */
        tmStatMfd.setTotalQtyAcc(new BigDecimal(tmStatMfd.getTotalQtyAcc()).add(new BigDecimal(tmStatMfdDay.getTotalQtyAcc())).toString());
        /* 营销活动单日累计-总预算累计消耗金额 */
        tmStatMfd.setTotalAmtAcc(new BigDecimal(tmStatMfd.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTotalAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
        /* 营销活动单日累计-总预算累计消耗笔数 */
        tmStatMfd.setTxnQtyAcc(new BigDecimal(tmStatMfd.getTxnQtyAcc()).add(new BigDecimal(tmStatMfdDay.getTxnQtyAcc())).toString());
        /* 营销活动单日累计-总预算累计消耗金额 */
        tmStatMfd.setTxnAmtAcc(new BigDecimal(tmStatMfd.getTxnAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTxnAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
    }
}
